2

如何去識別並從圖像中提取矩形(如下圖所示)。如何在openCV中識別不完整的矩形

請注意,我的矩形可能不完整,並且有一些缺失邊緣,並且一些邊可能是局部線條。

謝謝!

image sample

+1

這是心理學研究的一部分,稱爲「格式塔心理學」。根據維基百科,你正在尋找「關閉法則」。第一個谷歌點擊之一是:http://users.acin.tuwien.ac.at/arichtsfeld/files/2012-ICPR-Richtsfeld。PDF,但也許你可以找到更多的一些研究後使用這些關鍵字。 – Micka

+1

Phew。超出我的理解範圍。但如果我沒有得到更簡單的解決方案,我會檢查一下!謝謝 – lucidxistence

+0

我會說通常這不是一個簡單的任務!但是,對於您的應用程序,可能存在足夠簡單的啓發式。 – Micka

回答

2

這可以使用morphological操作來解決,例如eroding and dilating。這兩個操作將幫助創建閉合的矩形。 之後,您可以使用此page的教程來檢測簡單的形狀,如矩形。

我實施了一個適用於您提供的圖像的快速演示。


main.py:

​​

侵蝕增厚所有的線,所以要回我們需要侵蝕後擴張正常寬度。我建議一次評論擴張操作,看看侵蝕是如何起作用的,反之亦然。 這個操作將會像這樣轉換你的圖像this

我使用的檢測算法需要黑色背景上的白線。 這就是爲什麼我們需要反轉圖像。

cv2.bitwise_not (dilate, dilate) 

之後,我們可以使用教程中的代碼。

image = dilate 
resized = imutils.resize(image, width=300) 
ratio = image.shape[0]/float(resized.shape[0]) 

# convert the resized image to grayscale, blur it slightly, 
# and threshold it 
gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY) 
blurred = cv2.GaussianBlur(gray, (5, 5), 0) 
thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1] 
#thresh = dilate 
# find contours in the thresholded image and initialize the 
# shape detector 
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, 
    cv2.CHAIN_APPROX_SIMPLE) 
cnts = cnts[0] if imutils.is_cv2() else cnts[1] 
sd = ShapeDetector() 

# loop over the contours 
for c in cnts: 
    # compute the center of the contour, then detect the name of the 
    # shape using only the contour 
    M = cv2.moments(c) 
    cX = int((M["m10"]/M["m00"]) * ratio) 
    cY = int((M["m01"]/M["m00"]) * ratio) 
    shape = sd.detect(c) 

    # multiply the contour (x, y)-coordinates by the resize ratio, 
    # then draw the contours and the name of the shape on the image 
    c = c.astype("float") 
    c *= ratio 
    c = c.astype("int") 
    cv2.drawContours(image, [c], -1, (0, 255, 0), 2) 
    cv2.putText(image, shape, (cX, cY), cv2.FONT_HERSHEY_SIMPLEX, 
     0.5, (255, 255, 255), 2) 

    # show the output image 
    cv2.imshow("Image", image) 
    cv2.waitKey(0) 

shapeDetector.py:

# import the necessary packages 
import cv2 

class ShapeDetector: 
    def __init__(self): 
     pass 

    def detect(self, c): 
     # initialize the shape name and approximate the contour 
     shape = "unidentified" 
     peri = cv2.arcLength(c, True) 
     approx = cv2.approxPolyDP(c, 0.04 * peri, True) 
     # if the shape is a triangle, it will have 3 vertices 
     if len(approx) == 3: 
      shape = "triangle" 

     # if the shape has 4 vertices, it is either a square or 
     # a rectangle 
     elif len(approx) == 4: 
      # compute the bounding box of the contour and use the 
      # bounding box to compute the aspect ratio 
      (x, y, w, h) = cv2.boundingRect(approx) 
      ar = w/float(h) 

      # a square will have an aspect ratio that is approximately 
      # equal to one, otherwise, the shape is a rectangle 
      shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle" 

     # if the shape is a pentagon, it will have 5 vertices 
     elif len(approx) == 5: 
      shape = "pentagon" 

     # otherwise, we assume the shape is a circle 
     else: 
      shape = "circle" 

     # return the name of the shape 
     return shape 

結果:

enter image description here

+0

@Jeru Luke The問題說:「我將如何去確認和提取矩形[...]。請注意,我的矩形可能不完整,所以我覺得我的回答非常適合。 –

0

我建議服用霍夫變換來識別感興趣的角度,然後在霍夫空間識別對角的大質量正好90度,然後在每一個這樣的對循環的不同,識別顯著表示空間所有這些「垂直」和「水平」線候選者的偏移量,並且從那裏使用一些啓發式來從這些正交線候選者中識別可能的矩形。

例如,在確定了給定角度對的一組線條之後,您可能會有相對較少的線條進行評估,因此您可以做更多的事情,像蠻力O(N^2)的線尋找相關的角落(在一側定義爲「空」,而在另一側定義爲「密集」),然後匹配角落以製作矩形列表。