opencv2:圆检测未检测到明显的圆
opencv2: Circle detection not detecting the obvious ones
问题
我正在尝试使用 opencv2 在静止图像中检测 PlayStation Move 运动控制器。为了增加球体和背景之间的对比度,我决定修改输入图像以自动缩放每个通道的图像平均水平和 96 以上的亮度水平,然后在转换为灰度时,取最大值默认变换,因为一些球体是饱和的但不是 "bright".
然而,我在调整参数方面的最佳尝试似乎效果不佳,检测到明显圆圈上不存在的圆圈。
如何提高检测的准确性?您认为我可以使用哪些其他改进或算法?
样本
从最好到最差的顺序:
2 个魔杖,检测到 1 个魔杖(显示所有 2 个检测到的圆圈)
2 根魔杖,检测到 1 根魔杖有许多 none 存在的圆圈(显示前 4 个圆圈)
1 根魔杖(深色背景),总共 6 个圆圈,其中排名最低的是正确的(显示所有 6 个圆圈)
1 根魔杖(黑色背景),总共检测到 44 个圆圈,none 其中是那个魔杖(显示所有 44 个圆圈)
我正在使用这个函数调用:
cv2.HoughCircles(img_gray,cv2.HOUGH_GRADIENT,
dp=1, minDist=24, param1=90, param2=25,
minRadius=2, maxRadius=48)
所有图像都调整大小并裁剪为 640x480(PS3 眼睛的分辨率)。不执行模糊。
我认为 hough 圆圈对你来说是错误的方法,因为你并不是真的在寻找圆圈。您正在寻找强度高的圆形区域。使用例如代替斑点检测,我链接了一个指南:
https://www.learnopencv.com/blob-detection-using-opencv-python-c/
在斑点检测中,需要设置参数以获得合适的高强度圆形区域。
正如其他用户所说,霍夫圆不是这里最好的方法,因为霍夫圆只寻找完美的圆。而你的目标是 "circular" 但不是圆圈(由于运动模糊、光线 bleed/reflection、噪音等)
我建议将图像转换为 HSV,然后通过 hue/color 和强度过滤以获得二进制阈值,而不是直接使用灰度(这将有助于去除背景和噪声并限制搜索区域)
然后使用 findContours()(比 blob 检测更快),检查高圆度和预期 size/area 范围甚至坚固性的轮廓。
area = cv2.contourArea(contour)
perimeter = cv2.arcLength(contour,True)
circularity = 4*np.pi*area / (perimeter**2)
solidity = area/cv2.contourArea(cv2.convexHull(contour))
您最大的问题是由于低对比度导致球体轮廓与背景融合。所以也许一些 adaptive threshold 可以帮助
问题
我正在尝试使用 opencv2 在静止图像中检测 PlayStation Move 运动控制器。为了增加球体和背景之间的对比度,我决定修改输入图像以自动缩放每个通道的图像平均水平和 96 以上的亮度水平,然后在转换为灰度时,取最大值默认变换,因为一些球体是饱和的但不是 "bright".
然而,我在调整参数方面的最佳尝试似乎效果不佳,检测到明显圆圈上不存在的圆圈。
如何提高检测的准确性?您认为我可以使用哪些其他改进或算法?
样本
从最好到最差的顺序:
2 个魔杖,检测到 1 个魔杖(显示所有 2 个检测到的圆圈)
2 根魔杖,检测到 1 根魔杖有许多 none 存在的圆圈(显示前 4 个圆圈)
1 根魔杖(深色背景),总共 6 个圆圈,其中排名最低的是正确的(显示所有 6 个圆圈)
1 根魔杖(黑色背景),总共检测到 44 个圆圈,none 其中是那个魔杖(显示所有 44 个圆圈)
我正在使用这个函数调用:
cv2.HoughCircles(img_gray,cv2.HOUGH_GRADIENT,
dp=1, minDist=24, param1=90, param2=25,
minRadius=2, maxRadius=48)
所有图像都调整大小并裁剪为 640x480(PS3 眼睛的分辨率)。不执行模糊。
我认为 hough 圆圈对你来说是错误的方法,因为你并不是真的在寻找圆圈。您正在寻找强度高的圆形区域。使用例如代替斑点检测,我链接了一个指南:
https://www.learnopencv.com/blob-detection-using-opencv-python-c/
在斑点检测中,需要设置参数以获得合适的高强度圆形区域。
正如其他用户所说,霍夫圆不是这里最好的方法,因为霍夫圆只寻找完美的圆。而你的目标是 "circular" 但不是圆圈(由于运动模糊、光线 bleed/reflection、噪音等)
我建议将图像转换为 HSV,然后通过 hue/color 和强度过滤以获得二进制阈值,而不是直接使用灰度(这将有助于去除背景和噪声并限制搜索区域)
然后使用 findContours()(比 blob 检测更快),检查高圆度和预期 size/area 范围甚至坚固性的轮廓。
area = cv2.contourArea(contour)
perimeter = cv2.arcLength(contour,True)
circularity = 4*np.pi*area / (perimeter**2)
solidity = area/cv2.contourArea(cv2.convexHull(contour))
您最大的问题是由于低对比度导致球体轮廓与背景融合。所以也许一些 adaptive threshold 可以帮助