【问题标题】:How to identify incomplete rectangles in openCV如何在openCV中识别不完整的矩形
【发布时间】:2017-11-01 20:50:13
【问题描述】:

我将如何从如下图所示的图像中识别和提取矩形。

请注意,我的矩形可能不完整,并且有一些缺失的边缘,一些边可能是部分线条。

谢谢!

【问题讨论】:

  • 这是心理学研究的一部分,称为“格式塔心理学”。根据维基百科,您正在寻找“闭合法则”。最早的谷歌点击之一是:users.acin.tuwien.ac.at/arichtsfeld/files/…,但也许您可以在使用这些关键字进行一些研究后找到更多信息。
  • 唷。远远超出我的理解范围。但如果我没有得到更简单的解决方案,我会检查一下!谢谢
  • 我会说一般来说这不是一项简单的任务!但是对于您的应用程序来说,可能有足够的简单启发式方法。
  • Alan Gibson 在下一页展示了一些非常有用的技术来修补断线(尽管使用 ImageMagick)——我相信它们可以很容易地适应 OpenCV im.snibgo.com/mendbrkln.htm

标签: python opencv image-processing image-segmentation scikit-image


【解决方案1】:

这可以使用morphological 操作如eroding and dilating 来解决。这两个操作将有助于创建闭合矩形。 之后,您可以使用此page 中的教程来检测简单的形状,例如矩形。

我实现了一个适用于您提供的图像的快速演示。


ma​​in.py:

import cv2
import numpy as np
from shapeDetector import ShapeDetector
import imutils

img = cv2.imread('t.png')
kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 10)
dilate = cv2.dilate(erosion,kernel,iterations = 10)

侵蚀使所有线条变粗,因此要恢复正常宽度,我们需要在侵蚀后进行扩张。我建议评论一次扩张操作,看看侵蚀是如何工作的,反之亦然。 此操作将像这样转换您的图像

我使用的检测算法需要黑色背景上的白色线条。 这就是我们需要反转图像的原因。

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

结果:

【讨论】:

  • @Jeru Luke 问题是:“我将如何识别和提取矩形 [...]。请注意,我的矩形可能不完整 [...]。所以我觉得我的回答非常适合。
【解决方案2】:

我建议采用 Hough 变换来识别感兴趣的角度,然后识别 Hough 空间中质量较大且相差 90 度的角度对,然后循环遍历每个这样的对,识别所有此类“垂直”的显着表示的空间偏移" 和 "水平" 候选线,并从那里使用一些启发式方法从这些正交线候选中识别可能的矩形。

例如,在确定给定角度对的一组线后,您可能需要评估的线数量相对较少,因此您可以执行类似强力 O(N^2) 的操作,通过对线来寻找相关的角(定义为一侧为“空”,另一侧在两个方向上为“密集”),然后将角匹配成一个矩形列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 2014-03-27
    • 2017-03-08
    相关资源
    最近更新 更多