python - 如果使用OpenCV的HoughCircles,是否有推荐的方法来确定minRadius以便在图像中找到1个圆?

标签 python image opencv tensorflow crop

我需要找出选择OpenCV cv2.HoughCircles function中使用的minRadius值的最佳方法。

我正在努力提高可进行美国稀有硬币分类的Tensorflow CNN的准确性。目前,美国有线电视新闻网(CNN)正在审查的> 10k张图像,所有尺寸从300x300到1024x1024

为了提高模型的准确性,我尝试在训练之前将硬币从图像中拉出,并且仅在硬币上而不是在其周围训练模型。

下面的代码在将硬币检测为圆形时可以正常工作,但是我必须尝试几个minRadius值才能使HoughCircles函数正常工作。

在某些情况下,minRadius = 270在600x600和785x1024上有效,而在其他情况下,只有r = 200在600x600和785x1024上有效,但在785x1024上无效。在其他情况下,只有r = 318有效,而没有317或319有效。我没有找到一致的方法。

问题:是否存在建议的方法来确定minRadius以在图像中找到1个圆?假设图像大小不同且硬币占图像的50%至90%

这是典型图像的示例:https://i.ebayimg.com/images/g/r5oAAOSwH8VeHNBf/s-l1600.jpg
https://i.ebayimg.com/images/g/~JsAAOSwGtdeyFfU/s-l1600.jpg

image = cv2.imread(r"C:\testimages\70a.jpg")
output = image.copy()
height, width = image.shape[:2]

minRadius = 200
maxRadius =0

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(image=gray, 
                           method=cv2.HOUGH_GRADIENT, 
                           dp=1.2, 
                           minDist=200*minRadius, #something large since we are looking for 1
                           param1=200,
                           param2=100,
                           minRadius=minRadius,
                           maxRadius=maxRadius
                          )

#Draw the circles detected
if circles is not None:
    # convert the (x, y) coordinates and radius of the circles to integers
    circlesRound = np.round(circles[0, :]).astype("int")
    # loop over the (x, y) coordinates and radius of the circles
    for (x, y, r) in circlesRound:
        cv2.circle(output, (x, y), r, (0, 255, 0), 4)

    plt.imshow(output)
else:
    print ('No circles found')

最佳答案

这是通过将椭圆拟合到从阈值图像中提取的最大轮廓来实现的。如果需要,可以使用椭圆的主要半径和次要半径作为霍夫圆的近似值。

输入:

enter image description here

import cv2
import numpy as np

# read input
img = cv2.imread('s-l1600.jpg')

# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# apply morphology open and close
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (21,21))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)

# find largest contour
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)

# fit ellipse to contour and get ellipse center, minor and major diameters and angle in degree 
ellipse = cv2.fitEllipse(big_contour)
(xc,yc),(d1,d2),angle = ellipse
print('center: ',xc,',',yc)
print('diameters: ',d1,',',d2)

# draw ellipse
result = img.copy()
cv2.ellipse(result, ellipse, (0, 0, 255), 2)

# draw circle at center
xc, yc = ellipse[0]
cv2.circle(result, (int(xc),int(yc)), 5, (0, 255, 0), -1)

cv2.imwrite("s-l1600_thresh.jpg", thresh)
cv2.imwrite("s-l1600_morph.jpg", morph)
cv2.imwrite("s-l1600_ellipse.jpg", result)

cv2.imshow("s-l1600_thresh", thresh)
cv2.imshow("s-l1600_morph", morph)
cv2.imshow("s-l1600_ellipse", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

大津阈值图像:

enter image description here

清除阈值图像:

enter image description here

根据输入的轮廓拟合绘制椭圆,显示椭圆的轮廓和中心:

enter image description here

椭圆参数:
center:  504.1853332519531 , 524.3350219726562
diameters:  953.078125 , 990.545654296875

这是您的其他图片。但是这里我使用了inRange()的颜色阈值。

输入:

enter image description here
import cv2
import numpy as np

# read input
img = cv2.imread('s-l1600b.jpg')

# convert to hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# get color bounds of red circle
lower =(0,0,0) # lower bound for each channel
upper = (150,150,150) # upper bound for each channel

# create the mask and use it to change the colors
thresh = cv2.inRange(hsv, lower, upper)

# apply morphology open and close
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (31,31))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)

# find largest contour
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)

# fit ellipse to contour and get ellipse center, minor and major diameters and angle in degree 
ellipse = cv2.fitEllipse(big_contour)
(xc,yc),(d1,d2),angle = ellipse
print('center: ',xc,',',yc)
print('diameters: ',d1,',',d2)

# draw ellipse
result = img.copy()
cv2.ellipse(result, ellipse, (0, 0, 255), 2)

# draw circle at center
xc, yc = ellipse[0]
cv2.circle(result, (int(xc),int(yc)), 5, (0, 255, 0), -1)

cv2.imwrite("s-l1600_thresh.jpg", thresh)
cv2.imwrite("s-l1600_morph.jpg", morph)
cv2.imwrite("s-l1600_ellipse.jpg", result)

cv2.imshow("s-l1600b_thresh", thresh)
cv2.imshow("s-l1600b_morph", morph)
cv2.imshow("s-l1600b_ellipse", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

阈值图片:

enter image description here

形态清除图像:

enter image description here

拟合椭圆并在输入上绘制的最大外部轮廓:

enter image description here

椭圆参数:
center:  497.53564453125 , 639.7144165039062
diameters:  454.8548583984375 , 458.95843505859375

关于python - 如果使用OpenCV的HoughCircles,是否有推荐的方法来确定minRadius以便在图像中找到1个圆?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62205025/

相关文章:

python - Pandas Dataframe 部分字符串替换

php - 为什么PHP上传的一些图片会自动旋转90度?

python - 两幅图像之间的特征匹配和检测

image - 使用 cli 查找所有像素的平均值

c++ - OpenCV:是否可以在 Linux 中的进程之间共享网络摄像头

python - 将可变长度字符串数组转换为数据帧

python - 无法查看静态方法中的变量

python - flask : "from app import app"?

iphone - 微笑的瀑布

c++ - 图像的opencv中以下两行之间有什么区别