python - 两个相似形状之间的 OpenCV 形状匹配
问题描述
我正在尝试将稍微不规则的形状与形状数据库相匹配。例如,这里是我要匹配的轮廓:
有关更多信息,这是 HDMI 连接器的轮廓,表示为轮廓。这有点粗糙,因为这是在拿着 HDMI 时用手机拍摄的。
这是我的连接器数据库:
这些轮廓要清晰得多,因为这些轮廓是从互联网上的连接器图像中收集的。
对于我所尝试的:
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 是我唯一的选择(我宁愿避免,因为我没有适当数量的数据)。
解决方案
此答案基于 ZdaR 在此处的答案https://stackoverflow.com/a/55530040/1787145。cv2.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))
推荐阅读
- python-3.x - 如何将树的所有dfs路径存储在列表中?
- json - 将 JSON 字符串作为值传递给 Spring 数据 REST 端点
- wordpress - 当购物车总金额 = 0 时,应显示货到付款
- c# - 该类型不包括任何可访问的构造函数 WPF - 无窗口应用程序
- c++ - 使用线性探测插入哈希表
- phpword - 使用 PHPWord 添加纸张大小
- html - 如何在 dart 中使用 beautifulsoup scrape 从网页中获取特定元素
- java - 如何表示 Optional 类型的属性
在 OpenAPI 3 上 - sql - H2 嵌入式 DB LIMIT + OFFSET> Integer.MAX_VALUE 导致错误结果
- python - 如何以不同的时间安排间隔运行 subdags?