使用OpenCV和Python围绕特定点旋转X度的图像

99

我很难找到使用OpenCV和Python旋转图像特定点和特定(通常非常小的)角度的示例。

这是我目前所拥有的,但它产生了一个非常奇怪的结果图像,虽然它已经做了一些旋转:

def rotateImage( image, angle ):
    if image != None:
        dst_image = cv.CloneImage( image )

        rotate_around = (0,0)
        transl = cv.CreateMat(2, 3, cv.CV_32FC1 )

        matrix = cv.GetRotationMatrix2D( rotate_around, angle, 1.0, transl )
        cv.GetQuadrangleSubPix( image, dst_image, transl )
        cv.GetRectSubPix( dst_image, image, rotate_around )

    return dst_image
12个回答

166
import numpy as np
import cv2

def rotate_image(image, angle):
  image_center = tuple(np.array(image.shape[1::-1]) / 2)
  rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
  result = cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR)
  return result

假设您正在使用cv2版本,该代码找到要旋转的图像中心,计算变换矩阵并应用于图像。


1
我想我可能有所进展,但仍然遇到问题。这是最新的代码:result = cv2.warpAffine(image, rot_mat, cv.GetSize(image), flags=cv2.INTER_LINEAR)Traceback (most recent call last): result = cv2.warpAffine(image, rot_mat, cv.GetSize(image), flags=cv2.INTER_LINEAR) TypeError: <unknown> 不是一个numpy数组 - Mike
15
我运行cv2.getRotationMatrix2D(center=image_center ,angle=angle,scale=1)时出现问题。TypeError:该函数需要精确的2个参数,但提供了3个。 - Hani
6
image.shape包括图像的宽度、高度和通道数。 - Treper
4
请问需要将这段话翻译成哪种语言? - sreemanth pulagam
3
angle 的单位为度。 https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html?highlight=getrotationmatrix#getrotationmatrix2d - Eduardo Pignatelli
显示剩余3条评论

79

或者更容易地使用SciPy

from scipy import ndimage

#rotation angle in degree
rotated = ndimage.rotate(image_to_rotate, 45)

点击此处获取更多用法信息。


1
我正在遍历一个PNG目录并执行此操作,但是我收到了一个RuntimeError:指定的旋转平面无效。有任何修复方法吗? - Teodorico Levoff
你是否传入了一个OpenCV图像?例如:img = cv2.imread('messi5.jpg',0) - fivef
14
对我来说,这很慢。 - Ali Momen Sani
7
好的,它更易于使用,并且您可以轻松决定是否要保留图像大小(reshape=True)还是图像内容(reshape=False)。 - AljoSt
这对我来说很好。 - Jimut123

23
def rotate(image, angle, center = None, scale = 1.0):
    (h, w) = image.shape[:2]

    if center is None:
        center = (w / 2, h / 2)

    # Perform the rotation
    M = cv2.getRotationMatrix2D(center, angle, scale)
    rotated = cv2.warpAffine(image, M, (w, h))

    return rotated

17

我对上述一些解决方案有疑问,无法正确获取图像的“bounding_box”或新尺寸。因此,这里是我的版本。

def rotation(image, angleInDegrees):
    h, w = image.shape[:2]
    img_c = (w / 2, h / 2)

    rot = cv2.getRotationMatrix2D(img_c, angleInDegrees, 1)

    rad = math.radians(angleInDegrees)
    sin = math.sin(rad)
    cos = math.cos(rad)
    b_w = int((h * abs(sin)) + (w * abs(cos)))
    b_h = int((h * abs(cos)) + (w * abs(sin)))

    rot[0, 2] += ((b_w / 2) - img_c[0])
    rot[1, 2] += ((b_h / 2) - img_c[1])

    outImg = cv2.warpAffine(image, rot, (b_w, b_h), flags=cv2.INTER_LINEAR)
    return outImg

这是用于人脸检测的吗?我想将视频帧旋转90度并运行MTCNN,因为它无法检测侧躺的正面人脸(人躺在地上)。 - mLstudent33
@mLstudent33 不,我是用它进行了不同的目的,但这只是旋转图像而已。所以如果你有角度的话应该没问题吧? - JTIM
1
我认为可以。我可以旋转,运行检测,然后绘制 cv2.rectangle(),最后再将其旋转回来。谢谢回复。 - mLstudent33

13

cv2.warpAffine函数中的shape参数是反向的:(列,行),以上答案没有提到这一点。这是对我有效的方法:

import numpy as np

def rotateImage(image, angle):
    row,col = image.shape
    center=tuple(np.array([row,col])/2)
    rot_mat = cv2.getRotationMatrix2D(center,angle,1.0)
    new_image = cv2.warpAffine(image, rot_mat, (col,row))
    return new_image

getRotationMatrix2D 似乎也需要 (col,row)。center 也应该像 @Omnipresent 的答案中所做的那样使用 (col,row)。 - erwaman
我同意这并不清晰。@alex-rodrigues的答案对图像进行了一些切片操作,以便在warpAffine中正确获取宽度和高度:image.shape [1 :: -1]就是这样做的。这样做的原因是从第一个元素开始取一个步长为-1的切片,所以向左移动,最终得到一个包含[1] [0]的切片,即宽度(列),后跟高度(行)。 - Keithel

7

我能在旋转的帧上运行人脸检测吗?MTCNN无法检测侧躺的正面人脸。 - mLstudent33

6

5
这个代码 imutils.rotate_bound(frame, 90) 不会裁剪任何图像,它会将图像旋转90度并自动调整大小。 - Ali Momen Sani

4
快速调整@alex-rodrigues的答案...包括形状和通道数量。
import cv2
import numpy as np

def rotateImage(image, angle):
    center=tuple(np.array(image.shape[0:2])/2)
    rot_mat = cv2.getRotationMatrix2D(center,angle,1.0)
    return cv2.warpAffine(image, rot_mat, image.shape[0:2],flags=cv2.INTER_LINEAR)

1
你需要一个大小为2x3的齐次矩阵。前2x2是旋转矩阵,最后一列是平移向量。

enter image description here

以下是构建转换矩阵的方法:

# Exemple with img center point:
# angle = np.pi/6
# specific_point = np.array(img.shape[:2][::-1])/2

def rotate(img: np.ndarray, angle: float, specific_point: np.ndarray) -> np.ndarray:
    warp_mat = np.zeros((2,3))
    cos, sin = np.cos(angle), np.sin(angle)
    warp_mat[:2,:2] = [[cos, -sin],[sin, cos]]
    warp_mat[:2,2] = specific_point - np.matmul(warp_mat[:2,:2], specific_point)
    return cv2.warpAffine(img, warp_mat, img.shape[:2][::-1])

0

这是一个使用OpenCV仅围绕任意点(x,y)旋转的示例

def rotate_about_point(x, y, degree, image):
    rot_mtx = cv.getRotationMatrix2D((x, y), angle, 1)
    abs_cos = abs(rot_mtx[0, 0])
    abs_sin = abs(rot_mtx[0, 1])
    rot_wdt = int(frm_hgt * abs_sin + frm_wdt * abs_cos)
    rot_hgt = int(frm_hgt * abs_cos + frm_wdt * abs_sin)
    rot_mtx += np.asarray([[0, 0, -lftmost_x],
                           [0, 0, -topmost_y]])
    rot_img = cv.warpAffine(image, rot_mtx, (rot_wdt, rot_hgt),
                            borderMode=cv.BORDER_CONSTANT)
    return rot_img

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接