簡體   English   中英

OpenCV Python:繪制 minAreaRect(未實現 RotatedRect)

[英]OpenCV Python: Draw minAreaRect ( RotatedRect not implemented)

是否有任何輔助方法可以繪制由cv2.minAreaRect()返回的旋轉矩形,大概為((x1,y1),(x2,y2),angle) cv2.rectangle()不支持角度。 並且由於返回的元組不屬於“RotatedRect”類(因為它似乎沒有在 Python 綁定中實現),因此沒有points()方法,如 C++ 教程“為輪廓創建邊界旋轉框和橢圓”中所示¶ ”

如何從直線繪制旋轉的矩形 - 圍繞中心點或給定的第一個點旋轉?

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

我知道很久以前就有人問過這個問題,但是我想分享一種與接受的答案提出的方法不同的方法,也許這對其他人有幫助(實際上這已經在 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)

我想,可以使用類似的方法根據其中心而不是其相對左上角的初始點來定義旋轉矩形,但我還沒有嘗試過。

這是繪制旋轉矩形的具體示例。 這個想法是用Otsu 的閾值獲得一個二值圖像,然后使用cv2.findContours找到輪廓。 我們可以得到使用旋轉矩形cv2.minAreaRect和使用四個角落的頂點cv2.boxPoints 要繪制矩形,我們可以使用cv2.drawContourscv2.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()

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)

根據@ 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。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM