【问题标题】:OpenCV Python rotate image by X degrees around specific pointOpenCV Python围绕特定点将图像旋转X度
【发布时间】:2012-02-20 22:29:41
【问题描述】:

我很难找到使用 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

【问题讨论】:

    标签: python opencv rotation


    【解决方案1】:
    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 版本,该代码会找到您要旋转的图像的中心,计算变换矩阵并应用于图像。

    【讨论】:

    • 我想我可能已经取得了一些进展,但仍然遇到了问题。这是最新的代码: result = cv2.warpAffine(image, rot_mat, cv.GetSize(image), flags=cv2.INTER_LINEAR) Traceback(最近一次调用最后): result = cv2.warpAffine(image, rot_mat, cv.GetSize (图像), flags=cv2.INTER_LINEAR) TypeError: is not a numpy array
    • 我在运行 cv2.getRotationMatrix2D(center=image_center ,angle=angle,scale=1) 时遇到问题 TypeError: function 只需要 2 个参数(给定 3 个)
    • image.shape 包含宽度、高度和通道
    • @Hani 试试 cv2.getRotationMatrix2D((imagecenter[0],imagecenter[1]),angle,1.0)
    【解决方案2】:

    或者更容易使用 SciPy

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

    here 了解更多使用信息。

    【讨论】:

    • 我正在循环一个 png 目录并执行此操作,但我得到一个 RuntimeError: invalid rotation plane specified。有什么修复吗?
    • 你是否传递了一个打开的简历图像?来自:img = cv2.imread('messi5.jpg',0)
    • 这对我来说很慢
    • 很好,它更易于使用,并且您可以轻松决定是要保持图像大小 (reshape=True) 还是图像内容 (reshape=False)
    【解决方案3】:
    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
    

    【讨论】:

      【解决方案4】:

      cv2.warpAffine 函数以相反的顺序获取形状参数: (col,row) 上面的答案没有提到。这对我有用:

      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 也应该使用 (col,row),就像在 @Omnipresent 的回答中所做的那样。
      • 我同意不清楚。 @alex-rodrigues 的回答对 image.shape 进行了一些切片,以便按照正确的顺序为 warpAffine 获得宽度和高度: image.shape[1::-1] 这样做。它的作用是从第一个元素开始切片,步长值为 -1,因此向左移动,最终得到一个带有 [1][0] 的切片,即宽度(列),然后是高度(行)。
      【解决方案5】:

      在获取正确的“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 不,我将它用于不同的目的,但这只是旋转图像。所以如果你有角度,那应该没问题?
      • 我想是的。我可以旋转,运行检测,然后绘制cv2.rectangle(),然后将其旋转回来。感谢您的回复。
      【解决方案6】:
      import imutils
      
      vs = VideoStream(src=0).start()
      ...
      
      while (1):
         frame = vs.read()
         ...
      
         frame = imutils.rotate(frame, 45)
      

      更多:https://github.com/jrosebr1/imutils

      【讨论】:

      • 这个不会剪切任何图像:imutils.rotate_bound(frame, 90)
      【解决方案7】:

      您可以简单地使用 imutils 包进行旋转。它有两种方法

      1. rotate:以指定角度旋转图像。但是缺点是如果不是方形图像,图像可能会被裁剪。
      2. Rotate_bound:它克服了旋转时出现的问题。它会在旋转图像时相应地调整图像的大小。

      您可以在此博客上获得更多信息: https://www.pyimagesearch.com/2017/01/02/rotate-images-correctly-with-opencv-and-python/

      【讨论】:

      • 我可以在旋转的框架上运行人脸检测吗? MTCNN 不会检测到侧身的正面。
      【解决方案8】:

      快速调整@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)
      

      【讨论】:

        【解决方案9】:

        您可以使用 opencv python 轻松旋转图像-

        def funcRotate(degree=0):
            degree = cv2.getTrackbarPos('degree','Frame')
            rotation_matrix = cv2.getRotationMatrix2D((width / 2, height / 2), degree, 1)
            rotated_image = cv2.warpAffine(original, rotation_matrix, (width, height))
            cv2.imshow('Rotate', rotated_image)
        

        如果您正在考虑创建一个轨迹栏,那么只需使用cv2.createTrackbar() 创建一个轨迹栏,然后从您的主脚本中调用funcRotate()fucntion。然后,您可以轻松地将其旋转到您想要的任何角度。有关实现的完整详细信息也可以在这里找到-Rotate images at any degree using Trackbars in opencv

        【讨论】:

          【解决方案10】:

          这是一个仅使用 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
          

          【讨论】:

            【解决方案11】:

            您可以使用以下代码:

            import numpy as np
            from PIL import Image
            import math
            def shear(angle,x,y):
            
            tangent=math.tan(angle/2)
            new_x=round(x-y*tangent)
            new_y=y
            
            #shear 2
            new_y=round(new_x*math.sin(angle)+new_y)     
            #since there is no change in new_x according to the shear matrix
            
            #shear 3
            new_x=round(new_x-new_y*tangent)            
            #since there is no change in new_y according to the shear matrix
            
            return new_y,new_x
            
            
            
            
            image = np.array(Image.open("test.png"))            
            # Load the image
            angle=-int(input("Enter the angle :- "))               
            # Ask the user to enter the angle of rotation
            
            # Define the most occuring variables
            angle=math.radians(angle)                             
            #converting degrees to radians
            cosine=math.cos(angle)
            sine=math.sin(angle)
            
            height=image.shape[0]                                
            #define the height of the image
            width=image.shape[1]                                    
            #define the width of the image
            
            # Define the height and width of the new image that is to be formed
            new_height  = round(abs(image.shape[0]*cosine)+abs(image.shape[1]*sine))+1
            new_width  = round(abs(image.shape[1]*cosine)+abs(image.shape[0]*sine))+1
            
            
            output=np.zeros((new_height,new_width,image.shape[2]))
            image_copy=output.copy()
            
            
            # Find the centre of the image about which we have to rotate the image
            original_centre_height   = round(((image.shape[0]+1)/2)-1)    
            #with respect to the original image
            original_centre_width = round(((image.shape[1]+1)/2)-1)   
            #with respect to   the original image
            
            # Find the centre of the new image that will be obtained
            new_centre_height= round(((new_height+1)/2)-1)        
            #with respect to the new image
            new_centre_width= round(((new_width+1)/2)-1)          
            #with respect to the new image
            
            
            for i in range(height):
             for j in range(width):
                #co-ordinates of pixel with respect to the centre of original image
                y=image.shape[0]-1-i-original_centre_height                   
                x=image.shape[1]-1-j-original_centre_width 
            
                #Applying shear Transformation                     
                new_y,new_x=shear(angle,x,y)
            
               
                new_y=new_centre_height-new_y
                new_x=new_centre_width-new_x
                
                output[new_y,new_x,:]=image[i,j,:]                        
            
                pil_img=Image.fromarray((output).astype(np.uint8))                       
                pil_img.save("rotated_image.png")       
            

            【讨论】:

              【解决方案12】:

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

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

              # 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])
              

              【讨论】:

                猜你喜欢
                • 2023-04-07
                • 2013-06-30
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-10-16
                相关资源
                最近更新 更多