【问题标题】:OpenCV Python: Draw minAreaRect ( RotatedRect not implemented)OpenCV Python:绘制 minAreaRect(未实现 RotatedRect)
【发布时间】:2013-08-14 22:57:11
【问题描述】:

是否有任何辅助方法可以绘制由cv2.minAreaRect() 返回的旋转矩形,推测为((x1,y1),(x2,y2),angle)cv2.rectangle() 不支持角度。 而且由于返回的元组不属于“RotatedRect”类(因为它似乎没有在 Python 绑定中实现),因此没有 points() 方法,如 C++ 教程 "Creating Bounding rotated boxes and ellipses for contours¶" 中所示。

如何从直线绘制旋转矩形 - 围绕中心点或给定的第一个点旋转?

【问题讨论】:

    标签: python opencv


    【解决方案1】:
    rect = cv2.minAreaRect(cnt)
    box = cv2.cv.BoxPoints(rect) # cv2.boxPoints(rect) for OpenCV 3.x
    box = np.int0(box)
    cv2.drawContours(im,[box],0,(0,0,255),2)
    

    应该可以解决问题。

    来源:

    1) http://opencvpython.blogspot.in/2012/06/contours-2-brotherhood.html

    2) Python OpenCV Box2D

    【讨论】:

    • @handle:未来读者的附加信息:以上答案是 OpenCV 2.4.x 版本的最佳选择。 OpenCV 3.x 即将发布。它具有相同的功能cv2.boxPoints(rect)cv2.cv.BoxPoints(rect) 将被删除。
    • 对于不使用“minAreaRect”功能的人,可以自定义旋转矩形结构为“rot_rect = ((x, y), (width, height), angle)”
    • box = np.int0(box) 行是做什么的?
    • @csg 它将box 的值转换为整数
    【解决方案2】:

    我知道这是很久以前问过的,但我想分享一种与接受的答案提出的不同的方法,也许这对其他人有帮助(实际上这已经在 C++ 中完成了,但似乎python 仍然缺少RotatedRect 类)。

    这个想法是从一个角度、一个大小(W 和 H)和一个初始点来定义一个旋转的矩形。这个初始点是相对左上角(相同大小的矩形的左上角,没有旋转角度)。从这里可以得到四个顶点,这样我们就可以用四条线绘制旋转的矩形。

    class RRect:
      def __init__(self, p0, s, ang):
        self.p0 = (int(p0[0]),int(p0[1]))
        (self.W, self.H) = s
        self.ang = ang
        self.p1,self.p2,self.p3 = self.get_verts(p0,s[0],s[1],ang)
        self.verts = [self.p0,self.p1,self.p2,self.p3]
    
      def get_verts(self, p0, W, H, ang):
        sin = numpy.sin(ang/180*3.14159)
        cos = numpy.cos(ang/180*3.14159)
        P1 = (int(self.H*sin)+p0[0],int(self.H*cos)+p0[1])
        P2 = (int(self.W*cos)+P1[0],int(-self.W*sin)+P1[1])
        P3 = (int(self.W*cos)+p0[0],int(-self.W*sin)+p0[1])
        return [P1,P2,P3]
    
      def draw(self, image):
        print(self.verts)
        for i in range(len(self.verts)-1):
          cv2.line(image, (self.verts[i][0], self.verts[i][1]), (self.verts[i+1][0],self.verts[i+1][1]), (0,255,0), 2)
        cv2.line(image, (self.verts[3][0], self.verts[3][1]), (self.verts[0][0], self.verts[0][1]), (0,255,0), 2)
    
    (W, H) = (30,60)
    ang = 35 #degrees
    P0 = (50,50)
    rr = RRect(P0,(W,H),ang)
    rr.draw(image)
    cv2.imshow("Text Detection", image)
    cv2.waitKey(200)
    

    我想,可以使用类似的方法来定义旋转矩形的中心,而不是其相对左上角的初始点,但我还没有尝试过。

    【讨论】:

      【解决方案3】:

      这是一个绘制旋转矩形的具体示例。想法是使用Otsu's threshold 获得二值图像,然后使用cv2.findContours() 找到轮廓。我们可以使用cv2.minAreaRect() 获得旋转的矩形,使用cv2.boxPoints() 获得四个角顶点。要绘制矩形,我们可以使用cv2.drawContours()cv2.polylines()


      输入->输出

      代码

      import cv2
      import numpy as np
      
      # Load image, convert to grayscale, Otsu's threshold for binary image
      image = cv2.imread('1.jpg')
      gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
      thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
      
      # Find contours, find rotated rectangle, obtain four verticies, and draw 
      cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
      cnts = cnts[0] if len(cnts) == 2 else cnts[1]
      rect = cv2.minAreaRect(cnts[0])
      box = np.int0(cv2.boxPoints(rect))
      cv2.drawContours(image, [box], 0, (36,255,12), 3) # OR
      # cv2.polylines(image, [box], True, (36,255,12), 3)
      
      cv2.imshow('image', image)
      cv2.waitKey()
      

      【讨论】:

        【解决方案4】:

        延伸 Tobias Hermann 的回答:如果您没有轮廓,而是由其中心点、尺寸和角度定义的旋转矩形:

        import cv2
        import numpy as np
        
        # given your rotated rectangle is defined by variables used below
        
        rect = ((center_x, center_y), (dim_x, dim_y), angle)
        box = cv2.cv.BoxPoints(rect) # cv2.boxPoints(rect) for OpenCV 3.x
        box = np.int0(box)
        cv2.drawContours(im,[box],0,(0,0,255),2)
        

        【讨论】:

        • rect = ((center_x, center_y), (dim_x, dim_y), angle) 这是一个非常好的信息。谢谢你。
        【解决方案5】:

        根据@smajtks 的回答,我根据其中心而不是其相对的左上角初始点来定义旋转矩形。代码如下:

        class RRect_center:
          def __init__(self, p0, s, ang):
            (self.W, self.H) = s # rectangle width and height
            self.d = math.sqrt(self.W**2 + self.H**2)/2.0 # distance from center to vertices    
            self.c = (int(p0[0]+self.W/2.0),int(p0[1]+self.H/2.0)) # center point coordinates
            self.ang = ang # rotation angle
            self.alpha = math.radians(self.ang) # rotation angle in radians
            self.beta = math.atan2(self.H, self.W) # angle between d and horizontal axis
            # Center Rotated vertices in image frame
            self.P0 = (int(self.c[0] - self.d * math.cos(self.beta - self.alpha)), int(self.c[1] - self.d * math.sin(self.beta-self.alpha))) 
            self.P1 = (int(self.c[0] - self.d * math.cos(self.beta + self.alpha)), int(self.c[1] + self.d * math.sin(self.beta+self.alpha))) 
            self.P2 = (int(self.c[0] + self.d * math.cos(self.beta - self.alpha)), int(self.c[1] + self.d * math.sin(self.beta-self.alpha))) 
            self.P3 = (int(self.c[0] + self.d * math.cos(self.beta + self.alpha)), int(self.c[1] - self.d * math.sin(self.beta+self.alpha))) 
        
            self.verts = [self.P0,self.P1,self.P2,self.P3]
        
          def draw(self, image):
            # print(self.verts)
            for i in range(len(self.verts)-1):
              cv2.line(image, (self.verts[i][0], self.verts[i][1]), (self.verts[i+1][0],self.verts[i+1][1]), (0,255,0), 2)
            cv2.line(image, (self.verts[3][0], self.verts[3][1]), (self.verts[0][0], self.verts[0][1]), (0,255,0), 2)
        
        (W, H) = (30,60)
        ang = 35 #degrees
        P0 = (50,50)
        rr = RRect_center(P0,(W,H),ang)
        rr.draw(image)
        cv2.imshow("Text Detection", image)
        cv2.waitKey(200
        

        这里,矩形围绕其中心旋转,而不是从初始点 P0 开始。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-16
          • 1970-01-01
          • 2016-09-07
          • 2017-08-14
          • 2023-03-23
          相关资源
          最近更新 更多