从图像中检测圆形物体

Circular Object Detection from image

如何检测光学圆(空心和填充)?有没有什么方法可以概括地解决分割问题?

当我应用以下方法时,我无法检测到光圈:

import numpy as np
import cv2

image= cv2.imread("cropped.jpg")

lower_bound = np.array([0,0,0]) 
upper_bound = np.array([255,255,195])

blur_factor = (3,3)
image= cv2.blur(image, blur_factor)

mask = cv2.inRange(image, lower_bound, upper_bound)

kernel = np.ones((3,3),np.uint8)
closing = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

contours = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)[0]
contours.sort(key=lambda x:cv2.boundingRect(x)[0]) 

array = []
ii = 1

for c in contours:
    (x,y),r = cv2.minEnclosingCircle(c)
    center = (int(x),int(y))
    r = int(r)
    if r >= 12 and r<=15:
        cv2.circle(image,center,r,(0,255,0),2)
        array.append(center)

for i in array:
    text_color = (0, 0, 255)
    cv2.putText(image, str(ii), i, cv2.FONT_HERSHEY_SIMPLEX, 0.5, text_color, 2)
    ii = ii + 1

cv2.imshow("masked",mask)
cv2.imshow("circled",image)
cv2.waitKey(0)

你的问题不是很清楚,但我要继续,假设你想检测这些图像上的黑圈。
我不会深入研究平滑参数,我不认为这是这里的问题(不是很模糊的图像,并且易于分割)。您的代码适用于检测包含在具有特定半径的圆中的组件。您得到了一堆误报,因为 一个圆圈内的对象不一定是一个圆圈

考虑以下两个粉红色对象:使用您的代码,它们都被检测到具有相同半径的封闭圆(白色)

由于在这里我们很幸运地尝试检测完整的圆圈,这是一个易于识别的对象,我建议检查您检测到的每个圆圈,其中的对象是否占据了该圆圈的大部分。这将能够消除误报,例如上面示例中的粉线。

因此,只要对您的代码进行最少的调整,我会建议类似

import numpy as np
import cv2

image= cv2.imread(your_image)

lower_bound = np.array([0,0,0])
upper_bound = np.array([255,255,195])

blur_factor = (3,3)
image= cv2.blur(image, blur_factor)

mask = cv2.inRange(image, lower_bound, upper_bound)
maskg=np.copy(mask)

kernel = np.ones((3,3),np.uint8)
closing = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

contours = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)
contours=contours[1]

array = []
ii = 1

for c in contours:
    #for mask creation
    imgg=np.zeros(image.shape[0:2])

    (x,y),r = cv2.minEnclosingCircle(c)
    center = (int(x),int(y))
    r = int(r)
    if r >= 12 and r<=18:
        #potential interesting circle. Let's check if it's a full circle. Create a mask with only your full circle
        cv2.circle(imgg,center,r,255,-1)

        #mask your thresholded image by this mask
        masked=cv2.bitwise_and(maskg.astype(np.uint8),maskg.astype(np.uint8),mask=imgg.astype(np.uint8))

        #and count how much white pixels are in this mask (divided by the mask's area)
        circle_fullness=np.sum(masked)/(np.pi*r**2*255)

        #if more than X% of the area is indeed an object, than you've got yourself a full circle
        if circle_fullness>=0.8:
            #and then do you consider it as positive
            array.append(center)
            cv2.circle(image, center, r, (0, 255, 0), 2)

for i in array:
    text_color = (0, 0, 255)
    cv2.putText(image, str(ii), i, cv2.FONT_HERSHEY_SIMPLEX, 0.5, text_color, 2)
    ii = ii + 1

cv2.imshow("masked",mask)
cv2.imshow("circled",image)
cv2.waitKey(0)

结果[按需删除]