OpenCV 使用形态学运算计算重叠圆
OpenCV counting overlapping circles using morphological operation
这是我试图从中获取圆圈的图像。
我使用了灰度图像和侵蚀的差异来得到边界。
img_path= 'input_data/coins.jpg'
img = cv2.imread(img_path)
rgb,gray=getColorSpaces(img)
a,b=0,255
plt.figure(figsize=(12, 12))
erosion_se=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
erosion = cv2.erode(gray,erosion_se,iterations = 1)
boundary=gray-erosion
image, contours, hierarchy = cv2.findContours(boundary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
plt.imshow(boundary,'gray')
我可以得到大部分边界相对不同的圆圈。
我想做两件事
获取重叠的圆圈数。
找到接触图像边界的圆圈。
我可以通过将圆的半径与图像边界进行比较来确定。问题是 2 个特定的 blob 未被检测为圆圈。
circles = cv2.HoughCircles(boundary, cv2.HOUGH_GRADIENT, 1, 20,
param1=30,
param2=15,
minRadius=5,
maxRadius=20)
if circles is not None:
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
cv2.circle(img,(i[0],i[2]),i[3],(0,255,0),2)
cv2.circle(img,(i[0],i[2]),2,(0,0,255),3)
cv2.imshow('circles', img)
k = cv2.waitKey(0)
if k == 27:
cv2.destroyAllWindows()
下面是圆边界 HoughCircles 之后的输出 image.The 突出的大绿色圆圈是 undesired.I 我不确定为什么对于某些重叠区域,没有检测到圆圈。
与其使用要求圆圈为 "perfect" 圆圈并且在连接的斑点上不准确的 HoughCircles,不如使用简单的轮廓过滤方法。这是主要思想:
计算重叠圈数
- 单个圆的轮廓面积近似为
~375
- 查找轮廓,遍历轮廓并使用轮廓区域进行过滤
- 重叠圆的总和
为了找到接触图像边界的圆,我们将检测区域限制在图像外部的 10 个像素。我们在这张新图像上找到轮廓,然后使用轮廓区域进行过滤以确定接触圆
计算重叠圈数
转换为灰度和阈值化得到二值图像后,我们将单个blob/circle的轮廓区域近似为~375
。接下来我们在图像上找到轮廓并使用 cv2.contourArea()
进行过滤。为了确定是否存在重叠,我们将每个轮廓的面积除以单个圆的面积,然后使用 math.ceil()
找到上限。如果我们得到大于 1 的上限值,则意味着 blob 已连接,我们只需将上限值添加到我们的计数器
这是检测到的重叠圆圈
Overlapping: 213
找到接触图像边界的圆圈
想法是创建一个黑框来掩盖图像内部不在边界上的部分。我们可以用 cv2.fillPoly()
来做到这一点。从这里我们找到轮廓并使用轮廓区域进行过滤。这个想法是,如果斑点与某个阈值区域相比相对较大,则意味着斑点最有可能接触到边缘
这是填充的黑框和检测到的触摸圆圈
Touching: 10
import cv2
import numpy as np
import math
image = cv2.imread('1.jpg')
black_box = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
# Count overlapping circles
single_area = 375
overlapping = 0
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
blob_area = math.ceil(area/single_area)
if blob_area > 1:
overlapping += blob_area
cv2.drawContours(image, [c], -1, (36,255,12), 2)
# Find circles touching image boundary
h, w, _ = image.shape
boundary = 10
touching = 0
box = np.array(([boundary,boundary],
[w-boundary,boundary],
[w-boundary, h-boundary],
[boundary, h-boundary]))
cv2.fillPoly(black_box, [box], [0,0,0])
copy = black_box.copy()
copy = cv2.cvtColor(copy, cv2.COLOR_BGR2GRAY)
copy = cv2.threshold(copy, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
cnts = cv2.findContours(copy, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
if area > 100:
touching += 1
cv2.drawContours(black_box, [c], -1, (36,255,12), 2)
print('Overlapping:', overlapping)
print('Touching:', touching)
cv2.imshow('image', image)
cv2.imshow('black_box', black_box)
cv2.waitKey()
这是我试图从中获取圆圈的图像。
我使用了灰度图像和侵蚀的差异来得到边界。
img_path= 'input_data/coins.jpg'
img = cv2.imread(img_path)
rgb,gray=getColorSpaces(img)
a,b=0,255
plt.figure(figsize=(12, 12))
erosion_se=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
erosion = cv2.erode(gray,erosion_se,iterations = 1)
boundary=gray-erosion
image, contours, hierarchy = cv2.findContours(boundary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
plt.imshow(boundary,'gray')
我可以得到大部分边界相对不同的圆圈。 我想做两件事
获取重叠的圆圈数。
找到接触图像边界的圆圈。 我可以通过将圆的半径与图像边界进行比较来确定。问题是 2 个特定的 blob 未被检测为圆圈。
circles = cv2.HoughCircles(boundary, cv2.HOUGH_GRADIENT, 1, 20,
param1=30,
param2=15,
minRadius=5,
maxRadius=20)
if circles is not None:
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
cv2.circle(img,(i[0],i[2]),i[3],(0,255,0),2)
cv2.circle(img,(i[0],i[2]),2,(0,0,255),3)
cv2.imshow('circles', img)
k = cv2.waitKey(0)
if k == 27:
cv2.destroyAllWindows()
下面是圆边界 HoughCircles 之后的输出 image.The 突出的大绿色圆圈是 undesired.I 我不确定为什么对于某些重叠区域,没有检测到圆圈。
与其使用要求圆圈为 "perfect" 圆圈并且在连接的斑点上不准确的 HoughCircles,不如使用简单的轮廓过滤方法。这是主要思想:
计算重叠圈数
- 单个圆的轮廓面积近似为
~375
- 查找轮廓,遍历轮廓并使用轮廓区域进行过滤
- 重叠圆的总和
为了找到接触图像边界的圆,我们将检测区域限制在图像外部的 10 个像素。我们在这张新图像上找到轮廓,然后使用轮廓区域进行过滤以确定接触圆
计算重叠圈数
转换为灰度和阈值化得到二值图像后,我们将单个blob/circle的轮廓区域近似为~375
。接下来我们在图像上找到轮廓并使用 cv2.contourArea()
进行过滤。为了确定是否存在重叠,我们将每个轮廓的面积除以单个圆的面积,然后使用 math.ceil()
找到上限。如果我们得到大于 1 的上限值,则意味着 blob 已连接,我们只需将上限值添加到我们的计数器
这是检测到的重叠圆圈
Overlapping: 213
找到接触图像边界的圆圈
想法是创建一个黑框来掩盖图像内部不在边界上的部分。我们可以用 cv2.fillPoly()
来做到这一点。从这里我们找到轮廓并使用轮廓区域进行过滤。这个想法是,如果斑点与某个阈值区域相比相对较大,则意味着斑点最有可能接触到边缘
这是填充的黑框和检测到的触摸圆圈
Touching: 10
import cv2
import numpy as np
import math
image = cv2.imread('1.jpg')
black_box = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
# Count overlapping circles
single_area = 375
overlapping = 0
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
blob_area = math.ceil(area/single_area)
if blob_area > 1:
overlapping += blob_area
cv2.drawContours(image, [c], -1, (36,255,12), 2)
# Find circles touching image boundary
h, w, _ = image.shape
boundary = 10
touching = 0
box = np.array(([boundary,boundary],
[w-boundary,boundary],
[w-boundary, h-boundary],
[boundary, h-boundary]))
cv2.fillPoly(black_box, [box], [0,0,0])
copy = black_box.copy()
copy = cv2.cvtColor(copy, cv2.COLOR_BGR2GRAY)
copy = cv2.threshold(copy, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
cnts = cv2.findContours(copy, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
if area > 100:
touching += 1
cv2.drawContours(black_box, [c], -1, (36,255,12), 2)
print('Overlapping:', overlapping)
print('Touching:', touching)
cv2.imshow('image', image)
cv2.imshow('black_box', black_box)
cv2.waitKey()