答案 0 :(得分:3)
这可以使用morphological等eroding and dilating操作来解决。这两个操作将有助于创建闭合矩形。 之后,您可以使用此page中的教程来检测简单形状,例如矩形。
我实施了一个快速演示,适用于您提供的图像。
<强> main.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
<强>结果:强>
答案 1 :(得分:0)
我建议采用霍夫变换来识别感兴趣的角度,然后在霍夫空间中识别具有大质量的角度对恰好相差90度,然后在每个这样的对上循环,识别所有这些的显着表示的空间偏移&# 34;垂直&#34;和&#34;水平&#34;线候选者,并从那里使用一些启发法来识别来自这些正统线候选者的可能的矩形。
例如,在为给定角度对识别一组线后,您可能需要评估相对较少的线,因此您可以执行更强大的操作O(N ^ 2)搜索成对的线用于查找相关角点的线条(定义为&#34;空白&#34;在一侧和#34;密集&#34;在另一侧在两个方向上),然后匹配角落以生成矩形列表