灰度图像导致 HoughCircles() 方法不准确

问题描述

这是 openCV polygon detection 的后续。对于第二张图片,我没有检测到任何矩形,但这是因为我的阈值对于该图片不正确。

我使用了 otsu 阈值,并添加一个约束来移除检测到的小矩形和其他不相关的矩形。

import numpy as np
import cv2 as cv
import math

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



n=0

#rectangle parameters
width=0 
height=0

start_x=0 
start_y=0
end_x=0 
end_y=0

#houghcircles parameters     
minr=0 
maxr=0
mind=0

maxarea=0
area=0

output = img.copy()
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret2,th = cv.threshold(gray,255,cv.THRESH_BINARY+cv.THRESH_OTSU)



#rectangle detection

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),5)
    
    x = approx.ravel()[0]
    y = approx.ravel()[1]

    x1,y1,w,h = cv.boundingRect(approx)
    a=w*h    
    if len(approx) == 4 and x>15  :
            
        aspectRatio = float(w)/h
        if  aspectRatio >= 2.5 and a>50:          
          print(x1,h)
          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),255),3)
          cv.putText(output,"rectangle "+str(x1)+"," +str(y1-5),(x1,y1-5),cv.FONT_HERShey_COMPLEX,0.5,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)

cv.imshow("op1",output)

#circle detection,converting binary to decimal.

circles = cv.HoughCircles(gray,cv.HOUGH_GRADIENT,1,mind,param1=50,param2=20,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 and y<start_y+height and x<start_x+width):
        
        cf= ((x-start_x)*8)/width
        fp= cf-math.floor(cf)
        
        
        if(fp>0.50):
            idx=math.ceil(cf)
        else:
            idx=math.floor(cf)

        
        
        exp=int(4- (0.5* (idx+1)))
       
        n+= 2**exp
        print("circle",x,r)
        cv.circle(output,(x,y),r,3)
        cv.circle(output,2,3)
        
print(n)
cv.imshow("th",th)
cv.imshow("gray",gray)
cv.imshow('output',output)

cv.waitKey(0)
cv.destroyAllWindows()

最后的结果是这样的:

enter image description here

现在已成功检测到矩形,但未正确检测到圆。检测到的圆与目标圆的大小大致相同,这意味着 HoughCircles() 的参数是正确的,尽管没有在正确的位置检测到圆。

这可能是因为眩光导致圆圈在灰度图像中几乎消失(我在 HoughCircles() 方法中使用):

enter image description here

如何使用 HoughCircles() 方法处理此图像?

编辑:修复了代码中的一个错误。问题仍然存在,但是我用其他图像进行了测试,并且它与灰度图像足够好的图像一起使用:

enter image description here

解决方法

这是在 Python/OpenCV 中提取圆的一种方法。转换为LAB,分离B通道,然后在黑眼圈上阈值。

输入:

enter image description here

import cv2
import numpy as np

# load images
img = cv2.imread('4_sign.jpg')

# convert to LAB
lab = cv2.cvtColor(img,cv2.COLOR_BGR2LAB)

# separate B channel
b = lab[:,:,2]

# threshold and invert
thresh = cv2.threshold(b,105,255,cv2.THRESH_BINARY)[1]
thresh = 255 - thresh

# apply morphology to clean it up
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(7,7))
morph = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(11,11))
morph = cv2.morphologyEx(morph,cv2.MORPH_CLOSE,kernel)

# get min enclosing circle
# numpy points are (y,x),so need to transpose
points = np.argwhere(morph.transpose()>0)

center,radius = cv2.minEnclosingCircle(points)
print('center:',center,'radius:',radius)

# draw circle on copy of input
result = img.copy()
cx = int(round(center[0]))
cy = int(round(center[1]))
rr = int(round(radius))
cv2.circle(result,(cx,cy),rr,(255,255),2)

# save output
cv2.imwrite('4_sign_circle.jpg',result)

# display results
cv2.imshow('thresh',thresh)
cv2.imshow('morph',morph)
cv2.imshow('result',result)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

enter image description here

添加

这是一个使用 HoughCircles 的版本。

import cv2
import numpy as np

# load images
img = cv2.imread('4_sign.jpg')
ht,wd = img.shape[:2]
minhw = min(ht,wd)

# convert to LAB
lab = cv2.cvtColor(img,kernel)

# get circle from HoughCircles
min_dist = int(minhw/20)
circles = cv2.HoughCircles(morph,cv2.HOUGH_GRADIENT,1,minDist=min_dist,param1=100,param2=10,minRadius=30,maxRadius=60)
#print(circles)

result = img.copy()
for circle in circles[0]:
    # draw the circle on copy of input
    (x,y,r) = circle
    center = (x,y)
    radius = r
    print('center:',radius)
    x = int(x)
    y = int(y)
    cv2.circle(result,radius,2)

# save output
cv2.imwrite('4_sign_circle2.jpg',result)
cv2.waitKey(0)

结果:

enter image description here

文本信息:

center: (410.5,686.5) radius: 54.4

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...