Affine transformation of images is often used in computer vision data enhancement. The affine transformation we say refers to rigid body transformation, that is, two parallel lines are still parallel after affine transformation, while perspective transformation is not rigid body transformation and is not discussed in this article. Usually any combination of inversion, translation, rotation, scaling and tangent transformation is affine transformation. Affine transformations can be expressed by the following formula:

Where the rotation Angle acts on A, B, D, e, scale acts on a, B, D, and C, f, as shown in the figure below:

1. Cv2. GetRotationMatrix2D explanation

Opencv’s cv2.getRotationMatrix2D function retrieves the rotation transformation matrix. Input the center point coordinates (centerX,centerY), rotation Angle θ and scaling ratio 1, and give the M transformation matrix:


[ c o s Theta. s i n Theta. ( 1 c o s Theta. ) c e n t e r X + s i n Theta. c e n t e r Y s i n Theta. c o s Theta. ( 1 c o s Theta. ) c e n t e r Y + s i n Theta. c e n t e r X 0 0 1 ] \left[\begin{matrix} cosθ & -sinθ & (1-cos θ) * centerX + sinθ * centerY \\ sinθ & cosθ & (1-cos θ) * centerY + sinθ * centerX \\ 0 & 0 & 1 \end{matrix} \right]

How do we derive this affine transformation matrix? Affine transformation matrix using polar coordinate system is easier to reason. We first rotate a point based on the origin, as shown in the figure below. We rotate point V1 counterclockwise θ to point V2 with a scaling ratio of 1.

The Angle between the line V1 and the origin and the horizontal line a, and the Angle between the line V2 and the origin and the horizontal line b is equal to a plus theta. Calculate the rotation transformation matrix: let V1=(x1, y1), V2=(x2, y2)

But usually we rotate based on the center point, and if we want to rotate around any point (tx, ty), we can do 1. First shift the rotation point to the origin 2. Then perform the above rotation operation 3. Press the inverse operation of 1 to shift back to get the point transformation matrix of rotation around any point:

2. WarpAffine operation

2.1 Obtain m-matrix for affine transformation

The transformation matrix M is obtained, and the rotated image can be obtained by M transformation of each point of the image. This step can be obtained by warpAffine of OpencV. However, through the above operations, the large image will lose information after rotation, as shown below:

2.2 Expanding the Canvas

When the canvas size remains unchanged, some images will be exceeded and not fully displayed, so we need to expand the canvas as follows :new_H=int(w∗abs(sin(radias(Angle))+h∗abs(cos(radias(Angle)))))

New_W =int(h∗fabs(sin(radians(Angle))+w∗fabs(cos(radians(Angle)))))

The new canvas enlargement is based on the upper left corner of the original image. Therefore, on the transformation matrix M, we can adjust the translation parameter:

M [0, 2] + = (new_W – w) / 2

M + = [1, 2] (new_H – h) / 2

3. Image affine transformation code

Talk is cheap, show me the code. Directly on the code:

def affine_transform(image, angle, scale=1.0) :
    h, w = image.shape[:2]
    center_x, center_y = width // 2, height // 2
    
    M = cv2.getRotationMatrix2D((center_x, center_y), angle, scale)
    cos = np.abs(M[0.0])
    sin = np.abs(M[0.1])
    
    new_h = int(h * cos + w * sin)
    new_w = int(h * sin + w * cos)
    M[0.2] += (new_w − w) / 2
    M[0.1] += (new_h − h) / 2
    
    new_image = cv2.warpAffine(image, M, (new_w, new_h))
    return new_image
Copy the code

4. Single point affine transformation code

When we perform affine transformation data enhancement, we need to transform the coordinate points of the target.

def affine_points(points, center_x, center_y, h, w, scale=1.0) :
    points = np.array(points, dtype=np.float32)
    points = np.hstack((points, np.ones((points.shape[0].1))))
    
    M = cv2.getRotationMatrix2D((center_x, center_y), angle, scale)
    cos = np.abs(M[0.0])
    sin = np.abs(M[0.1])
    
    new_h = int(h * cos + w * sin)
    new_w = int(h * sin + w * cos)
    M[0.2] += (new_w − w) / 2
    M[0.1] += (new_h − h) / 2
    
    new_points = np.dot(M, points.T).T
    return new_points
Copy the code