📜  使用Python旋转图像而不切掉边 – OpenCV(1)

📅  最后修改于: 2023-12-03 14:49:50.538000             🧑  作者: Mango

使用Python旋转图像而不切掉边 – OpenCV

在使用 OpenCV 库旋转图像时,常常会遇到图像旋转后被切掉边缘的问题。如何避免这个问题呢?本文将介绍如何使用 Python 和 OpenCV 库旋转图像而不切掉边缘。

实现思路

旋转图像后,新图像的大小会发生变化,因此需要进行一定的变换使其不被裁剪。这里的实现思路是将旋转后的图像放置在一个足够大的画布上,并进行平移操作,使得原图像的中心点与新图像的中心点重合。

具体实现有以下几个步骤:

  1. 计算原图像的中心点坐标。
  2. 创建一个足够大的新图像。
  3. 将原图像放置在新图像的中心,并进行旋转操作。
  4. 计算旋转后的图像在新图像中的位置,并进行平移操作,使得原图像的中心点与新图像的中心点重合。
代码实现
import cv2
import numpy as np

def rotate_image(image: np.ndarray, angle: float) -> np.ndarray:
    """
    旋转图像,不裁剪边缘

    Args:
        image: 要旋转的图像,类型为 numpy.ndarray。
        angle: 旋转角度,单位为度。

    Returns:
        旋转后的图像,类型为 numpy.ndarray。
    """

    # 计算原图像的中心点坐标
    height, width = image.shape[:2]
    center_x, center_y = width / 2, height / 2

    # 创建一个足够大的新图像,并将原图像放置在其中心,进行旋转操作
    max_dim = int(np.sqrt(height ** 2 + width ** 2))
    rotated_image = np.zeros((max_dim, max_dim, 3), dtype=np.uint8)
    new_center_x, new_center_y = max_dim / 2, max_dim / 2
    M = cv2.getRotationMatrix2D((center_x, center_y), angle, 1.0)
    rotated_image[int(new_center_y - center_y):int(new_center_y - center_y + height),
                  int(new_center_x - center_x):int(new_center_x - center_x + width)] = cv2.warpAffine(image, M, (width, height))

    # 计算旋转后的图像在新图像中的位置,并进行平移操作
    x = new_center_x - center_x
    y = new_center_y - center_y
    dx = int(max_dim / 2 - new_center_x)
    dy = int(max_dim / 2 - new_center_y)
    dst_image = rotated_image[dy + y:dy + y + height, dx + x:dx + x + width]

    return dst_image

代码中的 rotate_image 函数接受两个参数,一个是要旋转的图像,另一个是旋转的角度。函数中的实现思路与上面提到的一致。

示例

下面的示例展示了如何使用 rotate_image 函数旋转图像。

# 读取图像
image = cv2.imread('test.jpg')

# 旋转角度
angle = 30

# 旋转图像
rotated_image = rotate_image(image, angle)

# 显示旋转前和旋转后的图像
cv2.imshow('Original Image', image)
cv2.imshow('Rotated Image', rotated_image)
cv2.waitKey(0)

其中 test.jpg 是需要旋转的图像文件名。在运行示例时,将会显示旋转前和旋转后的图像,如图所示:

旋转前后对比图

可以看到,在旋转后的图像中,边缘没有被切掉。

总结

本文介绍了如何使用 Python 和 OpenCV 库旋转图像而不切掉边缘。通过将旋转后的图像放置在一个足够大的画布上,并进行平移操作,使得原图像的中心点与新图像的中心点重合,从而避免了边缘被裁剪的问题。你可以直接使用本文中的代码,也可以根据自己的需求进行修改,以便更好地适应场景。