Reputation: 669
I am trying to do a shear transformation on images using python. I am using skimage (scikit-image), opencv or similar can also do the job i think. The problem is whenever I try to shear using affine transform and warp (skimage) the image appears "cropped" or "clipped" (some parts of the "sheared" image are lost) which has sense as far as shear transform moves pixels (involves a translation of pixels). I need that the "canvas" supporting the image scale so the "sheared" image fit in a new image but keeping all the information of the input image (image attached)
Upvotes: 3
Views: 6635
Reputation: 402
I got the same trouble and I finally manage to found a solution that work well with the images I tested. I was using the fact that I want to apply shear, rotation and translation transformation on the image.
If you want all your images to be the same size, then use an angle of 45 degrees because it's the angle that need the more space.
import numpy as np
import cv2
#Parameters of the affine transform:
angle = 45; #Angle in degrees.
shear = 1;
translation = 5;
type_border = cv2.BORDER_CONSTANT;
color_border = (255,255,255);
original_image = cv2.imread(name_image_file);
rows,cols,ch = original_image.shape;
#First: Necessary space for the rotation
M = cv2.getRotationMatrix2D((cols/2,rows/2), angle, 1);
cos_part = np.abs(M[0, 0]); sin_part = np.abs(M[0, 1]);
new_cols = int((rows * sin_part) + (cols * cos_part));
new_rows = int((rows * cos_part) + (cols * sin_part));
#Second: Necessary space for the shear
new_cols += (shear*new_cols);
new_rows += (shear*new_rows);
#Calculate the space to add with border
up_down = int((new_rows-rows)/2); left_right = int((new_cols-cols)/2);
final_image = cv2.copyMakeBorder(original_image, up_down, up_down,left_right,left_right,type_border, value = color_border);
rows,cols,ch = final_image.shape;
#Application of the affine transform.
M_rot = cv2.getRotationMatrix2D((cols/2,rows/2),angle,1);
translat_center_x = -(shear*cols)/2;
translat_center_y = -(shear*rows)/2;
M = M_rot + np.float64([[0,shear,translation + translat_center_x], [shear,0,translation + translat_center_y]]);
final_image = cv2.warpAffine(final_image , M, (cols,rows),borderMode = type_border, borderValue = color_border);
Example (where I put the border of "cv2.copyMakeBorder" and "cv2.getRotationMatrix2D" to white): Angle = -45 degrees. Shear = -0.5
Upvotes: 4