我目前正在对图像进行圆检测看起来像这样,但是有些墨滴合并并形成一些不规则的形状(原始图像中的红色标记)。我在opencv中使用houghcircle函数来检测圆圈。对于那些不规则的形状,该功能只能将它们检测为几个小圆圈,但我真的希望程序将不规则形状视为一个完整的大形状并得到一个像我在输出图像中绘制的大圆圈。
我的代码将检测所有圆圈并获得它们的直径。
这是我的代码:
def circles(filename, p1, p2, minR, maxR):
# print(filename)
img = cv2.imread(filename, 0)
img = img[0:1000, 0:1360]
l = len(img)
w = len(img[1])
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 25,
param1 = int(p1) ,param2 = int(p2), minRadius = int(minR), maxRadius = int(maxR))
diameter = open(filename[:-4] + "_diamater.txt", "w")
diameter.write("Diameters(um)\n")
for i in circles[0,:]:
diameter.write(str(i[2] * 1.29 * 2) + "\n")
count = 0
d = []
area = []
for i in circles[0,:]:
cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
count += 1
d += [i[2]*2]
area += [i[2]*i[2]*pi*1.286*1.286]
f = filename.split("/")[-1]
cv2.imwrite(filename[:-4] + "_circle.jpg", cimg)
# cv2.imwrite("test3/edge.jpg", edges)
print "Number of Circles is %d" % count
diaM = []
for i in d:
diaM += [i*1.286]
bWidth = range(int(min(diaM)) - 10, int(max(diaM)) + 10, 2)
txt = '''
Sample name: %s
Average diameter(um): %f std: %f
Drop counts: %d
Average coverage per drop(um^2): %f std: %f
''' % (f, np.mean(diaM), np.std(diaM), count, np.mean(area), np.std(area))
fig = plt.figure()
fig.suptitle('Histogram of Diameters', fontsize=14, fontweight='bold')
ax1 = fig.add_axes((.1,.4,.8,.5))
ax1.hist(diaM, bins = bWidth)
ax1.set_xlabel('Diameter(um)')
ax1.set_ylabel('Frequency')
fig.text(.1,.1,txt)
plt.savefig(filename[:-4] + '_histogram.jpg')
plt.clf()
print "Total area is %d" % (w*l)
print "Total covered area is %d" % (np.sum(area))
rt = "Number of Circles is " + str(count) + "\n" + "Coverage percent is " + str(np.divide(np.sum(area), (w*l))) + "\n"
return rt
答案 0 :(得分:1)
如果您仍想使用HoughCircles功能,您可以看看两个圆圈是否重叠并从中创建一个新圆圈。
答案 1 :(得分:1)
您可以使用minEnclosingCircle。找到图像的轮廓,然后应用该功能将形状检测为圆圈。
下面是一个带有c ++代码的简单示例。在你的情况下,我觉得你应该使用Hough-circle和minEnclosingCircle的组合,因为你图像中的某些圆圈彼此非常接近,有可能它们被检测为单个轮廓。
输入图片:
圈:
Mat im = imread("circ.jpg");
Mat gr;
cvtColor(im, gr, CV_BGR2GRAY);
Mat bw;
threshold(gr, bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
for(int idx = 0; idx >= 0; idx = hierarchy[idx][0])
{
Point2f center;
float radius;
minEnclosingCircle(contours[idx], center, radius);
circle(im, Point(center.x, center.y), radius, Scalar(0, 255, 255), 2);
}
答案 2 :(得分:0)
当你拥有如此美丽的分离和对比模式时,最简单的方法是使用形状索引。请参阅this paper或this poster。在这两种情况下,您都有一个形状索引列表。
感谢形状索引,您可以遵循以下内容:
在您的具体情况下,圆形是完美的圆形,我会使用以下形状索引:
也适用于您的情况: