如何用OpenCV Python准确检测空心圆(环)的位置?

Ant*_*ony 5 python opencv image-processing

我想确定此(静态视频)图像中注射器尖端的中心位置。尖端名义上是圆形的并且具有已知的尺寸和数量。

我目前正在笔尖上涂上红色墨水,以便更容易检测到它们。如果不必这样做就好了,但我认为如果没有它,检测将会非常困难。有人喜欢挑战吗?

我开始尝试 SimpleBlobDetector,因为它有一些很好的过滤功能。我无法弄清楚的一件事是如何让 SimpleBlobDetector 检测空心圆(环)?

然后我尝试了canny + hough,但圆检测太不稳定,位置跳来跳去。

我目前正在使用 findContours + minEnendingCircle ,它工作正常,但仍然很不稳定。面具看起来像这样。结果。可以看到准确率不是很高:

动图

我简单地查看了 RANSAC,但找不到可以检测多个圆的 Python 示例,而且边缘检测很棘手。

我当前的代码:

# /sf/ask/2276609261/
frame_inv = ~frame0
# Convert BGR to HSV
hsv = cv2.cvtColor(frame_inv, cv2.COLOR_BGR2HSV)
blur = cv2.GaussianBlur(hsv, (5, 5), 0)
# define range of color in HSV
lower_red = np.array([90 - 10, 70, 50])
upper_red = np.array([90 + 10, 255, 255])
# Threshold the HSV image to get only red colors
mask = cv2.inRange(hsv, lower_red, upper_red)
# cv2.imshow('Mask', mask)
kernel = np.ones((5, 5), np.uint8)
dilate = cv2.dilate(mask, kernel)
# cv2.imshow('Dilate', dilate)
contours = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]

tipXY = []
for c in contours:
    area = cv2.contourArea(c)
    if area > 200:
        (x, y), r = cv2.minEnclosingCircle(c)
        center = (int(x), int(y))
        r = int(r)
        shift = 2
        factor = 2 ** shift
        cv2.circle(frame0, (int(round((x) * factor)), int(round((y) * factor))),
                       int(round(10 * factor)), (0, 255, 0), 2, shift=shift)
        tipXY.append(center)
Run Code Online (Sandbox Code Playgroud)

对于提高位置检测精度/稳定性有什么建议吗?

Jer*_*uke 1

这是使用第二张图像作为输入来分割红色的更好方法。

主意:

由于红色很突出,我尝试转换为其他已知的色彩空间(LAB 和 YCrCb)并查看它们各自的通道。from更突出地表达CrYCrCb红色。根据此链接Cr通道代表红色和亮度之间的差异,使颜色脱颖而出。

代码:

img = cv2.imread('stacked_rings.jpg')

ycc = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
cr_channel = ycc[:,:,1]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

虽然可以看到空心环,但像素强度范围仅限于[109 - 194]范围。让我们扩大范围:

dst = cv2.normalize(cr_channel, dst=None, alpha=0, beta=255,norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

圆圈更加突出。希望这个预处理步骤对您有所帮助。