首页 > 解决方案 > 两个相似形状之间的 OpenCV 形状匹配

问题描述

我正在尝试将稍微不规则的形状与形状数据库相匹配。例如,这里是我要匹配的轮廓:

在此处输入图像描述

有关更多信息,这是 HDMI 连接器的轮廓,表示为轮廓。这有点粗糙,因为这是在拿着 HDMI 时用手机拍摄的。

这是我的连接器数据库:

HDMI:在此处输入图像描述

DVI:在此处输入图像描述

5针DIN:在此处输入图像描述

DB25:在此处输入图像描述

这些轮廓要清晰得多,因为这些轮廓是从互联网上的连接器图像中收集的。

对于我所尝试的:

cv2.matchShapes()

由于这些都只是轮廓,所以我尝试使用 matchShapes() 方法直接比较它们,但未能产生好的结果。不规则轮廓和我的数据库之间的相似之处是:

HDMI:0.90

DB25:0.84

5 针 DIN:0.5

DVI:0.21

由于轮廓越接近匹配结果越接近 0,该算法完全失败。我通过更改第三个参数尝试了其他匹配方法,但仍然不成功。

宝珠:

与 SIFT 类似,我尝试了关键点匹配。平均我的数据库中不同匹配之间的距离(在找到前 15% 的匹配之后):

mean([m.distance for m in matches])

距离如下:

五针DIN:7.6

DB25:11.7

DVI:12.1

HDMI:19.6

由于这将圆形归类为最像我的轮廓的形状,因此这也失败了。

以下是实际 HDMI 插槽的 ORB 与我的示例 HDMI 插槽的匹配关键点,以获取更多信息: 在此处输入图像描述

我应该尝试任何想法/其他算法吗?或者 CNN 是我唯一的选择(我宁愿避免,因为我没有适当数量的数据)。

标签: pythonopencvimage-processingimage-recognitionopencv-contour

解决方案


此答案基于 ZdaR 在此处的答案https://stackoverflow.com/a/55530040/1787145cv2.matchShapes()我已经尝试了一些变化,希望通过在预处理中加入更多来使用单一的辨别标准( )。

1.比较图像而不是轮廓

我喜欢规范化(裁剪和调整大小)的想法。但是在缩小图像后,由于像素分辨率低,其原本闭合的轮廓可能会被分解成多个不连贯的部分。的结果cv2.matchShapes()是不可靠的。通过比较整个调整大小的图像,我得到以下结果。它说圆圈是最相似的。不好!

在此处输入图像描述

2.填充形状

通过填充形状,我们考虑了面积。结果看起来更好,但 DVI 仍然优于 HDMI,因为它具有更相似的高度或高度/宽度比。我们想忽略这一点。

在此处输入图像描述

3.将每张图片调整为相同大小

通过将所有尺寸调整为相同尺寸,我们消除了尺寸中的一些比例。(300, 300) 在这里效果很好。

在此处输入图像描述

4. 代码

def normalize_filled(img):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    im, cnt, _ = cv2.findContours(img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    # fill shape
    cv2.fillPoly(img, pts=cnt, color=(255,255,255))
    bounding_rect = cv2.boundingRect(cnt[0])
    img_cropped_bounding_rect = img[bounding_rect[1]:bounding_rect[1] + bounding_rect[3], bounding_rect[0]:bounding_rect[0] + bounding_rect[2]]
    # resize all to same size
    img_resized = cv2.resize(img_cropped_bounding_rect, (300, 300))
    return img_resized

imgs = [imgQuery, imgHDMI, imgDVI, img5PinDin, imgDB25]
imgs = [normalize_filled(i) for i in imgs]

for i in range(1, 6):
    plt.subplot(2, 3, i), plt.imshow(imgs[i - 1], cmap='gray')
    print(cv2.matchShapes(imgs[0], imgs[i - 1], 1, 0.0))

推荐阅读