openCV中的轮廓匹配形状

Ola*_*lad 4 python opencv image image-processing

我是 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)
Run Code Online (Sandbox Code Playgroud)

img 是嘴巴的图像,比较是我用 photoshop 选择的同一图像中的一颗牙齿,所以我希望至少匹配那个。我目前的问题是唯一匹配的轮廓似乎是图像的框架。

有人可以指出我做错了什么或建议我更好的项目方法吗?图像大小是否与图像大小有关,如果是,调整图像大小的最佳方法是什么?

感谢您的时间!

Jib*_*iby 5

形状描述符是要走的路

为了匹配场景中几乎没有遮挡的对象,我建议先尝试关键点提取然后匹配,例如 SIFT(及其朋友 ORB、SURF ...)

我尝试使用此 SO 答案和您的数据对 SURF 模板匹配和可视化的代码进行超快速复制/粘贴,这很有希望:

冲浪匹配

它已经显示了 4 个似是而非的匹配!=)

这个怎么运作

您需要进行一些深入研究才能掌握算法,但基本思想在幕后保持不变:

  1. 给定一个模板图像,根据数学魔法找到兴趣点(角落、可识别的兴趣点)。这些是N“M”值的列表。这些值表示感兴趣点周围图像的统计信息(例如局部形状直方图、边缘信息...)
  2. 给定一个场景(包括模板),计算该图像的所有兴趣点。
  3. 通过在M维度上进行距离计算来寻找场景中类似模板的关键点:每个关键点就像 3D 中的一个点,匹配 2 个相似的关键点只不过是计算 3D 中点的距离并说“足够接近”! .
  4. 您现在有 2 组关键点,以及一个似是而非的关键点匹配列表。您现在正在尝试查看“给定 2D 向量列表,找到最合理的位移”(旋转、缩放、平移)

你的代码

我想你的代码对你的数据,这里是我通过可视得到edgescompare

 cv2.imshow("Edges",edges)
 cv2.waitKey(0)
Run Code Online (Sandbox Code Playgroud)

边缘

 cv2.imshow("compare",compare)
 cv2.waitKey(0)
Run Code Online (Sandbox Code Playgroud)

相比


这是什么意思

如您所见,您的edges图像有大量不相关的短边。这通常是参数选择太低的精明参数的副作用。

这可能会在很大程度上影响形状匹配,因为 OpenCV 尝试匹配“边缘对边缘”,而开放的边缘图可能会给出与compare图像不同的结果。

请参阅此python 食谱以可视化阈值选择和自动阈值选择器的影响。在任何情况下都非常有用=)

更普遍

让我们考虑一下您正在工作的限制,看看是否会出现识别牙齿的解决方案:

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

  • 嘴是由嘴唇定界的,有点。你可能会用那个?好吧,对于嘴唇很少或没有嘴唇的人来说很棘手。
  • 牙齿通常位于任何面上的相同位置(需要引用)。它很重要,因为人脸检测是一个经过充分研究的问题,并且在 OpenCV 中实现了几种可能对您有所帮助的算法(例如本教程)。一旦你有了嘴,你就有了一个盒子,你肯定会在它周围找到你的目标,大大缩小了问题的范围。

牙齿:

  • 几乎没有纹理信息(局部直方图形状没有直接帮助)
  • 亮度应高于图片周围嘴巴的平均水平
  • 几乎没有饱和度,与红色+高饱和度的嘴唇相反(除非变黄和其他有趣的东西)
  • 主要由与其他牙齿和背景(口腔/牙龈内部)的边缘分隔

您的图片:

  • 有颜色!
    • 意味着您可以通过 HSV 色彩空间访问更多信息
  • 仅针对一张脸