如何识别openCV中不完整的矩形 [英] How to identify incomplete rectangles in openCV

查看:2220
本文介绍了如何识别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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆