opencv 以任意角度旋转图片

发布时间 2023-04-22 15:20:41作者: 5p2o

opencv中有两种方式来对图像进行旋转操作:

  1. 使用rotate函数,通过rotateCode来控制图像的旋转角度,而rotateCode的取值只有90/180/270三种,自由度不够高。
  2. 使用仿射变换warpAffine来以任意角度的旋转图片。但旋转后的图片会被裁切,丢失了部分信息,代码与效果图如下所示:
import numpy as np
import cv2 as cv

img = cv.imread("lena.png", cv.IMREAD_UNCHANGED)
h, w, c = img.shape
m = cv.getRotationMatrix2D(center=(w / 2, h / 2), angle=45, scale=1)
ret = cv.warpAffine(img, m, img.shape[1::-1])
cv.imwrite("wrapAffine.png", ret)
lena.png wrapAffine.png

为解决上述问题,就有了如下代码

import numpy as np
import cv2 as cv
from typing import Tuple

def rotate(img: np.ndarray, angle: float, center: Tuple[float, float] = None) -> np.ndarray:
    h, w, c = img.shape
    # Defining the center point of rotation as the center of the image if center is not provided
    center = (w / 2, h / 2) if center is None else center
    # Ensuring that the center point lies within the image dimensions
    assert 0 <= center[0] <= w and 0 <= center[1] <= h

    # Adding a border of zeros around the input image to avoid cropping after rotation
    top, bottom, left, right = h, h, w, w
    bordered = cv.copyMakeBorder(img, top, bottom, left, right,
                                 borderType=cv.BORDER_CONSTANT, value=cv.BORDER_TRANSPARENT)
    # Computing the rotation matrix with respect to the center point of the image
    m = cv.getRotationMatrix2D(center=(center[0] + left, center[1] + top), angle=angle, scale=1)
    # Applying the rotation to the bordered image using the computed rotation matrix
    ret = cv.warpAffine(bordered, m, bordered.shape[1::-1], borderMode=cv.BORDER_TRANSPARENT)
    #  Removing the zero-padded border from the rotated image
    x, y = np.where(ret[..., -1] != 0)
    return ret[x.min():x.max(), y.min():y.max(), :]

使用rotate函数绕中心旋转45°的图片如下:

rotate