Numpy+PIL realizes free rotation of pictures

1. Introduction

Use PIL and Numpy programming to realize the free rotation of the picture.

2. Technical points

(1) Use the Python PIL library to read the image as a NumPy array.
(2) Adopt the image rotation transformation method of enlarging the image format after rotation, and calculate the rotation transformation matrix of the image pixels according to the rotation angle and the original image size.
(3) Use the rotation transformation matrix to calculate the pixel coordinates of the four vertices of the original image after rotation, calculate the new size of the rotated image by subtracting the minimum coordinate from the maximum coordinate, and create a NumPy array to store the new image.
(4) According to the method of reverse mapping , scan the pixels of the new image, determine the corresponding pixels of the original image through inverse transformation , and assign their RGB values ​​to the pixels of the new image.
(5) Save the NumPy array as image output.

3. Code implementation

def rotateImageWithZoom(image_path: str, rotate_angle: float):
    """
    放大图幅的图片旋转
    :param image_path: 图片路径
    :param rotate_angle: 旋转角度,单位:degree,顺时针为正
    :return: 新的图片numpy数组
    """
    img = Image.open(image_path)
    img_mat = np.asarray(img)
    beta = deg2rad(rotate_angle)
    h = img_mat.shape[0]
    w = img_mat.shape[1]
    K1 = np.array([[0, -1, 0.5 * h], [1, 0, 0.5 * w], [0, 0, 1]])
    K2 = np.array([[cos(beta), sin(beta), 0], [-sin(beta), cos(beta), 0], [0, 0, 1]])
    # 坐标变换矩阵
    K = np.matmul(K1, K2)
    # 旋转后左上角像素点位置
    left_up = np.matmul(K, np.array([[0], [0], [1]]))
    # 旋转后左下角像素点位置
    left_down = np.matmul(K, np.array([[h - 1], [0], [1]]))
    # 旋转后右上角像素点位置
    right_up = np.matmul(K, np.array([[0], [w - 1], [1]]))
    # 旋转后右下角像素点位置
    right_down = np.matmul(K, np.array([[h - 1], [w - 1], [1]]))
    # 确定外接矩形尺寸
    x1 = np.array([left_up.reshape((left_up.shape[0],)),
                   left_down.reshape((left_up.shape[0],)),
                   right_up.reshape((left_up.shape[0],)),
                   right_down.reshape((left_up.shape[0],))]).astype(int)
    # 旋转后图像尺寸
    new_h = np.max(x1[:, 0]) - np.min(x1[:, 0])
    new_w = np.max(x1[:, 1]) - np.min(x1[:, 1])
    x_min = np.min(x1[:, 0])
    y_min = np.min(x1[:, 1])
    # 新图像
    new_img_mat = np.ones((new_h, new_w, 3)) * 255
    # 反向映射
    K_inv = np.linalg.inv(K)
    for x in range(new_img_mat.shape[0]):
        for y in range(new_img_mat.shape[1]):
            old_pos = np.matmul(K_inv, np.array([[x + x_min + 1], [y + y_min + 1], [1]])).astype(int)
            if 0 <= old_pos[0] < h and 0 <= old_pos[1] < w:
                new_img_mat[x, y] = img_mat[old_pos[0], old_pos[1]]
    # numpy数组转图片
    new_img_mat = new_img_mat.astype(int)
    new_img = Image.fromarray(new_img_mat.astype(np.uint8))
    new_img.save('photos/rotated_photo_{}.png'.format(rotate_angle))
    plt.imshow(new_img_mat)
    plt.xlabel("${} ^0$".format(rotate_angle))
    plt.show()
    return new_img_mat.astype(int)

4. Realize the effect

The method of use is as follows:

if __name__ == '__main__':
    rotateImageWithZoom('photos/takagi.jpeg', -60.3)

Original image:
insert image description here

Rotation -60.3°:
insert image description here
Note: when matplotlib draws a picture, the x-axis is the picture height, the y-axis is the picture width, and the general picture viewer's x-axis is the width, and the y-axis is the height.

5. Result Analysis

The size of the rotated picture has changed significantly. After zooming in, it can also be seen that the picture rotated by -61.3° has become blurred. The reason is that each pixel is regarded as an ideal point without size during the rotation transformation, and the coordinates after rotation will be Decimals (that is, sub-pixel coordinates) appear, and the coordinates are rounded during reverse mapping, so there is a rounding error, resulting in the loss of some pixels. For the angles of 0°, 90°, 180° and -90°, the rounding error is 0, so there is no change in clarity after rotation except for the change of the frame.
Conclusion : When rotating and transforming an image, try to choose a special angle to avoid loss of pixels, resulting in a decrease in image quality. For non-special angles, such as -10°, -61.3°, etc., it needs to be deblurred after rotation to ensure that the clarity is basically unchanged. .

Guess you like

Origin blog.csdn.net/anbuqi/article/details/128414578