2017-04-05 168 views
0

如何检测光学圆(空心以及填充)?有没有什么办法可以一般化的方式解决segementation问题?圆形物体检测

我是不是能够检测到光圈时,我运用以下方法:

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

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

考虑以下两个粉红色的对象:你的代码,两者都与一个封闭的圆检测(白色)半径相同
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) 

结果[删除按需]

+0

你报价是创建与掩盖原来的限图像的图像线考虑的最小圈闭。意思是一个黑色的图像,除了最小的封闭圆内的区域,这将是你的阈值图像。试试代码和imshow()的东西:) 对于你的号码识别问题,这是一个完全不同的问题:检查OCR https://en.wikipedia.org/wiki/Optical_character_recognition,我认为有OpenCV中的实现。 – Soltius

+0

这是你的代码,我只是改变了数字。这个想法是寻找所有最小的封闭圆,并且只选择那些具有特定半径(在12和18之间)的圆,因为你知道那是你正在寻找的半径。 – Soltius

+0

你可以看看霍夫圆变换 – Soltius