Numpy+PIL realiza rotación libre de imágenes

1. Introducción

Use la programación PIL y Numpy para realizar la rotación libre de la imagen.

2. Puntos técnicos

(1) Use la biblioteca Python PIL para leer la imagen como una matriz NumPy.
(2) Se adopta el método de transformación de rotación de imagen para ampliar el tamaño de la imagen después de la rotación, y la matriz de transformación de rotación del píxel de la imagen se calcula de acuerdo con el ángulo de rotación y el tamaño de la imagen original.
(3) Use la matriz de transformación de rotación para calcular las coordenadas de píxeles de los cuatro vértices de la imagen original después de la rotación, calcule el nuevo tamaño de la imagen rotada restando la coordenada mínima de la coordenada máxima y cree una matriz NumPy para almacenar la nueva imagen.
(4) De acuerdo con el método de mapeo inverso , escanee los píxeles de la nueva imagen, determine el píxel de la imagen original correspondiente mediante transformación inversa y asigne su valor RGB al píxel de la nueva imagen.
(5) Guarde la matriz NumPy como salida de imagen.

3. Implementación del código

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. Date cuenta del efecto

El método de uso es el siguiente:

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

Imagen original:
inserte la descripción de la imagen aquí

Rotación -60,3°:
inserte la descripción de la imagen aquí
Nota: Cuando matplotlib dibuja una imagen, el eje x es la altura de la imagen y el eje y es el ancho de la imagen, mientras que el eje x del visor de imágenes general es el ancho y el eje y es la altura.

5. Análisis de resultados

El tamaño de la imagen rotada ha cambiado significativamente. Después de acercar el zoom, también se puede ver que la imagen rotada en -61.3° se ha vuelto borrosa. La razón es que cada píxel se considera un punto ideal sin tamaño durante la transformación de rotación, y las coordenadas después de la rotación aparecerán decimales (es decir, coordenadas de subpíxeles), y las coordenadas se redondean durante el mapeo inverso, por lo que hay un error de redondeo, lo que resulta en la pérdida de algunos píxeles. Para los ángulos de 0°, 90°, 180° y -90°, el error de redondeo es 0, por lo que no hay cambio en la claridad después de la rotación excepto por el cambio del marco.
Conclusión : Al rotar y transformar una imagen, trate de elegir un ángulo especial para evitar la pérdida de píxeles, lo que resulta en una disminución de la calidad de la imagen. Para ángulos no especiales, como -10°, -61,3°, etc., necesita para ser desenfocado después de la rotación para garantizar que la claridad no cambie básicamente .

Supongo que te gusta

Origin blog.csdn.net/anbuqi/article/details/128414578
Recomendado
Clasificación