从图像中检测圆形物体
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)
结果[按需删除]
如何检测光学圆(空心和填充)?有没有什么方法可以概括地解决分割问题?
当我应用以下方法时,我无法检测到光圈:
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)
结果[按需删除]