图像

时间:2017-04-05 13:08:33

标签: python opencv computer-vision optical-mark-recognition

如何检测光学圆圈(空心和填充)?是否有任何方法可以一般化地解决分割问题?

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

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)

1 个答案:

答案 0 :(得分:2)

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

考虑以下两个粉红色物体:使用您的代码,它们都被检测到具有相同半径的圆圈(白色) enter image description here

因为在这里我们很幸运能够尝试检测一个容易识别的完整圆形物体,我建议检查每个圆圈,检测它内部的物体是否占据了这个圆圈的大部分。这样可以消除误报,例如上面例子中的粉红线。

因此,只需对代码进行最少调整,我建议使用

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)

结果[按需删除]