2016-08-11 298 views
5

我正在对图像进行圆形检测,看起来像这样,但某些图形合并并形成一些不规则形状(原始图像中的红色标记)。我在opencv中使用houghcircle函数来检测圆圈。对于那些不规则的形状,该功能只能将它们检测为几个小圆圈,但我真的希望程序将不规则形状视为整个大形状,并在我的输出图像中画出一个大圆。使用houghcircle函数检测不规则形状opencv python

Original image

Output image

我的代码将检测所有的圈子,让他们直径的。

这里是我的代码:

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 

回答

1

如果你仍然想使用HoughCircles功能,你可以进去看看两个圆重叠,使一个新的圈子了出来。

+0

我已经试过这种方式,但有还有很多其他的圈子彼此相邻。所以它不能很好地工作。不管怎么说,还是要谢谢你。 –

1

您可以使用minEnclosingCircle。找到图像的轮廓,然后应用该功能将形状检测为圆形。

下面是一个简单的C++代码示例。在你的情况下,我觉得你应该使用Hough-circles和minEnclosingCircle的组合,因为图像中的一些圆圈彼此非常接近,有可能它们被检测为单个轮廓。

输入图像:

input

圈:

output

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); 
} 
0

当你拥有这样的美丽以及分离和对比模式,最简单的方法是使用形状指标。见this paperthis poster。在这两种情况下,您都有一个形状索引列表。

由于形态指标,你可以什么遵循:

  • 二进制图像
  • 连成分标签,以便分离每个图案
  • 计算形状指数(大部分都使用的基本措施)
  • 根据形状指标值对图案进行分类。

在你的具体情况下的圆形形状浑圆,我会用以下形状指标:

  • 圆度=>只用半径,所以最简单的计算和完善你的情况。
  • 拉伸/伸长/半径拉伸=>在您的情况下是完美的,但所有库中都不提供最小球计算。
  • 等周缺陷=>真的很容易计算,但由于周长而比稳定性稍差。

你的情况也包括工作:

  • 峡刻光盘
  • 传播莫顿
  • 赤字
  • 扩展通过直径