在openCV中进行轮廓匹配形状的操作

4

我刚接触openCV(使用Python)和图像处理,试图开始自己的项目来学习如何工作。我尝试从一张张嘴的图片中选出牙齿。我能想到的最好的解决方案是用牙齿的模板进行匹配,并根据从口腔图像获取的轮廓进行形状匹配。这可能不是最好的解决方案,但似乎相当容易实现。

到目前为止,我的代码如下:

img = cv2.imread('resources/1.jpg', cv2.IMREAD_COLOR)
compare = cv2.imread('resources/template.jpg', cv2.IMREAD_GRAYSCALE)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.bilateralFilter(gray, 11, 17, 17)
edges = cv2.Canny(gray, 20, 10)
compare = cv2.Canny(compare, 200, 200)

contours, _ = cv2.findContours(gray.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
compare_contours, _2 = cv2.findContours(compare.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

for c in contours:
    for c2 in compare_contours:
        ret = cv2.matchShapes(c, c2, 1, 0.0)
        if ret < 0.5:
            peri = cv2.arcLength(c, True)
            approx = cv2.approxPolyDP(c, 0.02 * peri, True)
            cv2.drawContours(img, [approx], -1, (0, 255, 0), 7)
是嘴巴的图片,“compare”是我用Photoshop选择的同一张图片中的一颗牙齿,所以我希望至少它们两者能匹配。但是,我目前遇到的问题是,唯一匹配的轮廓似乎只有图片的边框。
请问有人能指出我做错了什么,或者建议我更好的项目方法吗?图片大小是否与图像匹配有关,如果是,最好的调整图像大小的方法是什么?
感谢您的时间!

你能否发布源代码和模板的示例图片,以便我们可以复制它? - Jiby
http://imgur.com/2Ry0Yig :装载中...http://imgur.com/OPFQTPM :未找到页面 - Olaru Vlad
2个回答

5

形状描述符是解决问题的关键

如果要在场景中匹配一个几乎没有遮挡的物体,我建议尝试一下关键点提取和匹配,例如SIFT(以及其它的ORB、SURF等)。

我尝试了一个超级快速的复制/粘贴SURF模板匹配和可视化代码,使用这个SO答案和你的数据,效果不错:

SURF matching

已经显示出4个可能的匹配!=)

工作原理

你需要深入了解算法才能掌握其技巧,但在底层,基本思路仍然相同:

  1. 给定一个模板图像,在数学上找到感兴趣的点(角点、有特征的可识别点)。这些是'M'值的'N'列表。这些值表示点周围图像的统计信息(如局部形状直方图、边缘信息等)。
  2. 给定一个场景(包括模板),计算该图像的所有感兴趣点。
  3. 通过在'M'维度上进行距离计算,查找场景中类似于模板的关键点:每个关键点就像3D中的一个点,将2个关键点匹配为相似的只是计算3D中点之间的距离,并说“足够接近”!
  4. 现在你有了2组关键点和一组可能的关键点匹配列表。现在要尝试看看“给定一组2D向量,找到最合理的位移”(旋转、缩放、平移)。

你的代码

我尝试使用你的代码对你的数据进行处理,下面是可视化edgescompare的结果:

 cv2.imshow("Edges",edges)
 cv2.waitKey(0)

Edges

 cv2.imshow("compare",compare)
 cv2.waitKey(0)

比较


什么意思

您可以看到,您的edges图像具有大量无关的短边缘。这通常是由于canny参数选择过低而引起的副作用。

这可能会极大地影响形状匹配,因为OpenCV试图进行“边对边”的匹配,而开放的边缘映射可能会与compare图像产生不同的结果。

请参见此Python示例以可视化阈值选择和自动阈值选择器的影响。在任何情况下,都非常有启发性 =)

更一般地说

让我们思考您正在处理的限制,并查看是否出现了区分齿齿的解决方案:

您正在查看包含多个感兴趣特征的图像(1张嘴巴=数十颗牙齿),但正在尝试查找任何匹配项。没有“错误答案”,没有棘手的牙齿状物体可区分(与这个真正相关的SO问题相反)。

  • 嘴巴由唇部界定,有点像。您可以用那个吗?好的,对于唇部很少或根本没有的人来说是棘手的。
  • 牙齿通常位于任何脸部的相同位置(需要引用)。这很重要,因为面部检测是一个非常经过研究的问题,OpenCV中实现了多种算法可能会帮助您(例如,这个教程)。一旦您找到了嘴巴,就有一个框,您可以确定在其中找到目标,从而大大减少了问题的范围。

牙齿:

  • 几乎没有纹理信息(无法从局部直方图形状获得直接帮助)
  • 亮度应高于图片周围嘴巴的平均亮度
  • 几乎没有饱和度,与唇部相反,其颜色鲜艳+饱和度高(除非发黄等有趣的事情)
  • 主要由其与其他牙齿和背景(口腔/牙龈内部)的边缘界定

您的图像:

  • 有颜色!
    • 这意味着您可以通过HSV颜色空间获得更多信息
  • 仅针对一个人脸

我已经尝试使用不同的参数进行Canny边缘检测,但最终选择了这些参数,因为在主图像上得到了大多数轮廓,在模板上只得到了主要轮廓,这对我来说更自然。非常感谢您的帮助,我一定会继续学习! - Olaru Vlad
很好 =) 添加了一堆关于这个主题的通用想法,以帮助指导您。 - Jiby
非常感谢,我会根据你的想法尝试不同的方法,并进一步研究它! - Olaru Vlad
谢谢你,Jiby!我会抽出更多时间(如果有的话)来研究你发现的内容,并完成这个项目! - Olaru Vlad

0

cv2.matchShapes 的返回值已经改变了。现在你应该尝试使用 ret > 5 来找到正确的轮廓。

我曾经遇到过同样的问题,但当我使用最大的 ret 时,我的轮廓可以匹配正确的轮廓。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接