首页 > 解决方案 > openCV多边形检测

问题描述

我应该编写一个程序来处理这种类型的图像: 在此处输入图像描述

(所有图像都是这种格式:绿色矩形和蓝色圆圈)。圆圈代表数字的二进制表示。任务是检测圆圈后输出十进制数。

我的方法是先找到绿色矩形(我没有使用颜色遮罩,原因稍后解释)并获得它的宽度和高度。

接下来,我根据对称性推断圆的中心必须w/8,3w/8,5w/87w/8矩形的左边缘相距一定距离。(水平)。

所以,我使用HoughCircles()了方法,然后尝试用(2x-1)w/8. 显然,每个圆圈的十进制等值由exp=2^(4-x).所以,我用来n+=2**exp获得十进制表示。

我还使用矩形的坐标来近似 HoughCircles() 方法的适当 minRadius 和 maxRadius 值,以便不检测不必要的圆。

import numpy as np
import cv2 as cv

img = cv.imread("7.jpeg")

img_height,img_w,c=img.shape


n=0 #stores the decimal rep.

width=0 #dimensions of the rectangle
height=0

start_x=0 #starting coordinates of the rectangle
start_y=0
end_x=0 #ending '''''''
end_y=0
     
minr=0 #for the houghCircles() method
maxr=0
mind=0

output = img.copy()
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)


_, th = cv.threshold(gray, 240, 255, cv.THRESH_BINARY)
contours, _ = cv.findContours(th, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)

for contour in contours:
    approx = cv.approxPolyDP(contour, 0.01* cv.arcLength(contour, True), True)
    
    cv.drawContours(img, [approx], 0, (0, 0, 0), 5)
    x = approx.ravel()[0]
    y = approx.ravel()[1] 

    
    if len(approx) == 4 and x>15 :
        
        
        x1 ,y1, w, h = cv.boundingRect(approx)
        aspectRatio = float(w)/h
        if aspectRatio <= 0.95 or aspectRatio >= 1.05:

          
          width=w
          height=h
          start_x=x1
          start_y=y1
          end_x=start_x+width
          end_y=start_y+height
          cv.rectangle(output, (start_x,start_y), (end_x,end_y), (0,0,255),3)
          cv.putText(output, "rectangle "+str(x)+" , " +str(y-5), (x, y-5), cv.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
          

minr=int(17*width/192)
maxr=int(7*width/64)
mind=int(width//5)


print("start",start_x,start_y)
print("width",width)
print("height",height)
print("minr", minr)
print("maxr",maxr)
print("mind",mind)

gray = cv.medianBlur(gray, 5)
circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, 1, mind,param1=50, param2=30, minRadius=minr, maxRadius=maxr)

detected_circles = np.uint16(np.around(circles))

for (x, y ,r) in detected_circles[0, :]:
    if(y>start_y and x>start_x):
        
        print("center ", x,y)
        idx= int (((x-start_x)*8)//width) 
        exp=int(4- (0.5* (idx+1)))
        n+= 2**exp
        cv.circle(output, (x, y), r, (0, 0, 0), 3)
        cv.circle(output, (x, y), 2, (0, 255, 255), 3)
print(n)
cv.imshow('output',output)
cv.waitKey(0)
cv.destroyAllWindows()

对于这种类型的所有图像,这非常有效。但是,有一个小缺点:

测试图像的格式非常“漂亮”:所有图像都具有固定的宽度和高度,完全直立,每个图像中矩形和圆形的所有颜色在所有图像中都具有完全相同的阴影,等等。

然而,我们应该让代码更通用一点:为了也容纳“不太好”的图像。例如,这种风格的图像:

在此处输入图像描述

基本上相同的格式,但背景照明 + 支架不是完全直立的,这使得概括代码更具挑战性,我觉得。这就是我避免使用 HSV 颜色遮罩的原因,因为不会有一组适合所有图像的更高和更低的值。

但是,我尝试做的也失败了:它无法正确检测到矩形。我希望它能够检测到多个矩形,但是它在那些根本没有矩形的位置(而不是在有矩形的位置)检测矩形。

如何调整我的代码以使其更通用,以便正确处理第二种类型的图像?

标签: pythonopencvhough-transform

解决方案


推荐阅读