4

我正在研究应用程序来识别圆形/椭圆形状内的线状特征。形状如下所示(在此示出了两个):图像特征检测

Shapes

  • 的形状本身能够圆和椭圆形之间略有不同。
  • 形状内至多有5条线,它们在每个形状的大致相同的区域中找到。
  • 这些线在长度,厚度,旋转和曲率方面可能略有不同。
  • 这些线条有时可以轻触/相交。
  • 通常有5个,但偶尔会有一行可能完全丢失。
  • 我不关心颜色,黑色和白色阈值罚款。

每个对象(100 +以上)将被视频单独捕获;捕捉是手动/物理过程(即,我每次都拿着相机)。我可以完全控制相机,因此我可以为每次拍摄定位。

现在我正在尝试使用OpenCV来进行识别。我能够修改示例“脸部识别”应用程序以使用另一个Haar标识符XML文件,但这似乎只能处理外部圆/椭圆的检测。

我对产生每个样品的对象信息,描述该5条内部线以用于进一步处理:

{ 
    1: { length: 20, avg_thick: 2.3 }, 
    2: { length: 4, avg_thick: 2.0 }, 
    3: { length: 9.1, avg_thick: 2.1 }, 
    4: { length: 2, avg_thick: 1.9 }, 
    5: { length: 17, avg_thick: 2.1 } 
} 

这是我的第一个项目,涉及图像识别。我应该使用哪些算法或程序来进行研究?谢谢!

UPDATE:

由于图像将通过手拍照,它们不是纯的黑/白。尝试应用阈值使得形状内的(虚线)线条有时会消失。我怎样才能改善阈值结果?

+1

你看过霍夫变换吗? – WildCrustacean

+0

不,这是我第一个涉及图像识别的项目,所以我全新的。我会阅读有关的,谢谢。 – Harper

+0

它可能不适合这种应用,特别是如果线条弯曲,但值得一看。 – WildCrustacean

回答

4

如果线条近似直线,使用Hough transform找到所有的线条,和霍夫的圆形版本变换,以求各界/省略号(那么你可以检查被包围圆/椭圆已经发现,以及哪些线在它内部)。

如果线条不直:你的意思是“狭长的区域”而不是线条,对吧? :)你将不得不骷髅(可能首先是阈值)。有用的教程:“Skeletonization using OpenCV-Python”。由于您需要宽度(=从骨架到边缘的距离),请使用skimage.morphology.medial_axis(...,return_distance = True)。你可能还需要一些方法来通过每个骨架的分支并修剪短的分支(没有任何现成的东西已经这样做了,对不起)。

Haar类型的方法根本不起作用,它只适用于(即使在理论上)具有固定相对位置和形状的特征。您想要某种几何特征提取算法,而不是图像识别。

编辑:在样品Python代码:

import numpy, scipy, scipy.ndimage, skimage.morphology, matplotlib.pyplot 

img = scipy.ndimage.imread("test.png") 

# quick and dirty threshold 
binary_img = img[:,:,0] < 0.1 

# skeletonize 
skel_binary, skel_distances = skimage.morphology.medial_axis(binary_img, return_distance=True) 

# find individual lines 
structure_element = scipy.ndimage.generate_binary_structure(2,2) 
skel_labels, num_skel_labels = scipy.ndimage.measurements.label(skel_binary, structure=structure_element) 

for n in range(1, num_skel_labels + 1): 
    # make a binary label for this line 
    line = (skel_labels == n) 
    # calculate width from skeleton 
    mean_width = 2 * numpy.mean(skel_distances[ line ]) 
    print "line %d: width %f" % (n, mean_width) 
    # you need some way to find the ends of a line 
    # perhaps the most distant pair of points? 

# show the labels 
# the circle is also labelled 
# you need some way to check which label is the circle and exclude that 
matplotlib.pyplot.imshow(skel_labels) 
matplotlib.pyplot.show() 

Output from program above

这一个版本的那些产生你上面贴还(检查线宽作品)图像合理的结果图像放大了10倍。它不涉及相交线,也许你可以为此做一个图算法。此外,您还需要以某种方式排除外部圆圈(它似乎总是n = 1,因为标签是从左上角发现的,而第一个标签区域是圆圈)。

编辑:如何(或是否)阈值是一个有趣的问题。您可以尝试自动阈值处理,也许基于大津的方法,或基于高斯混合(example)。我认为你可能会得到最好的结果与某种统计模型的背景和前景色亮度,结合局部自适应阈值。真的取决于你的图像的性质。

+0

非常感谢您的帮助。您能否添加更多的细节并解决更新后的问题? – Harper

+0

非常好,谢谢! – Harper

1
  1. 镂空图像并跟踪每一行,然后您将获得每行的行数和长度。
  2. 对于每一行,计算面积(计算原始BW图像中黑色像素的数量),然后将其除以长度以找出平均厚度。
+0

非常感谢您的帮助。您能否添加更多的细节并解决更新后的问题? – Harper