如何识别openCV中不完整的矩形 [英] How to identify incomplete rectangles in openCV
问题描述
如何从图像中识别和提取矩形,如下图所示。
请注意,我的矩形可能不完整,边缘有些缺失,有些边可能是偏线。
谢谢!
这可以使用
我使用的检测算法需要黑色背景上的白线。
这就是为什么我们需要反转图像。
cv2.bitwise_not(扩张,扩张)
之后,我们可以使用教程中的代码。
image = dilate
resized = imutils.resize(image,width = 300)
ratio = image .shape [0] / float(resized.shape [0])
#将调整后的图像转换为灰度,稍微模糊,
#和阈值
grey = 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
#在阈值图像中找到轮廓并初始化
#形状检测器
cnts = cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL ,
cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts [0] if imutils.is_cv2()else cnts [1]
sd = ShapeDetector()
#top over c中c的轮廓
:
#计算轮廓的中心,然后仅使用轮廓
M = cv2.moments(c)检测
#形状的名称)
cX = int((M [m10] / M [m00])* ratio)
cY = int((M [m01] / M [m00]) *比率)
shape = sd.detect(c)
#将轮廓(x,y)乘以调整大小比例,
#然后在图像上绘制轮廓和形状名称
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)
#显示输出图像
cv2.imshow(图像,图像)
cv2.waitKey(0)
shapeDetector.py:
#import必要的包
import cv2
class ShapeDetector:
def __init __(self):
pass
def detect(self,c):
#初始化形状名称并近似轮廓
shape =unidentified
peri = cv2.arcLength(c,True)
约= cv2.approxPolyDP(c,0.04 * peri,Tru e)
#如果形状是三角形,它将有3个顶点
如果len(约)== 3:
shape =triangle
#如果形状有4个顶点,则它是正方形或
#矩形
elif len(约)== 4:
#计算轮廓的边界框并使用
#计算宽高比的边界框
(x,y,w,h)= cv2.boundingRect(约)
ar = w / float(h)
#方形的宽高比大约为
#等于1,否则,形状为矩形
shape =square如果ar> = 0.95且ar< = 1.05 else矩形
#如果形状是五边形,它将有5个顶点
elif len(约)== 5:
shape =pentagon
#否则,我们假设形状是一个圆圈
else:
shape =circle
#返回形状的名称
返回形状
结果:
How would I go around identifying and extracting rectangles from an image such as the one shown below.
Note that my rectangles might be incomplete and have some missing edges and some sides might be partial lines.
Thanks !
This can be solved using morphological operations such as eroding and dilating. This two operations will help creating closed rectangles. After that you can use the tutorial from this page to detect simple shapes such as rectangles.
I implemented a quick demo which worked for the image you provided.
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)
The erosion thickens all the lines, so to get back to a normal width we need to dilate after eroding. I recommend to comment the dilate operation once to see how erode works and vice versa. This operations will transform your image like this
The detection algorithm I used expects white lines on black background. Thats why we need to invert the image.
cv2.bitwise_not ( dilate, dilate )
After that, we can use the code from the tutorial.
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
Result:
这篇关于如何识别openCV中不完整的矩形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!