两个相似形状之间的OpenCV形状匹配 [英] OpenCV shape matching between two similar shapes

查看:85
本文介绍了两个相似形状之间的OpenCV形状匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to match a slightly irregular shape to a database of shapes. For example, here the contour I'm trying to match:

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

For more information, this is an outline of an HDMI connector, represented as a contour. It is slightly rough as this was taken with a phone while holding the HDMI.

这是我的连接器数据库:

This is my database of connectors:

HDMI:

DVI:

5PinDIN:

DB25:

这些轮廓更加清晰,因为这些轮廓是从互联网的连接器图像中收集的.

These are a lot clearer as these are contours gathered from connector images from the internet.

对于我尝试过的:

cv2.matchShapes()

cv2.matchShapes()

由于这些都是轮廓,因此我尝试使用matchShapes()方法直接比较它们,但结果不佳.不规则轮廓与我的数据库之间的相似之处是:

Since these are all just contours, I tried directly comparing them using the matchShapes() method, and it failed to produce good results. The similarities between the irregular contour, and my database was:

HDMI:0.90

HDMI: 0.90

DB25:0.84

DB25: 0.84

5针DIN:0.5

5 Pin DIN: 0.5

DVI:0.21

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

Since contours are more similar the closer to 0 the match result is, the algorithm completely failed. I tried the other methods of matching by changing the third parameter and was still unsuccessful.

ORB:

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

Being similar to SIFT, I tried keypoint matching. Averaging the distance between the different matches in my database (after finding the top 15% of matches):

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

距离出现为:

五针DIN:7.6

DB25:11.7

DB25: 11.7

DVI:12.1

HDMI:19.6

HDMI: 19.6

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

As this classified a circle as the shape most like my contour, this has failed as well.

以下是实际HDMI插槽与我的示例HDMI插槽的ORB中的匹配关键点,以获取更多信息:

Here are the matching key points from ORB of the actual HDMI slot vs my example HDMI slot for more information:

我应该尝试任何想法/其他算法吗?还是CNN是我唯一的选择(我宁愿避免使用它,因为我没有足够的数据量).

Are there any ideas/other algorithms I should try? Or is a CNN my only choice (which I would rather avoid as I don't have the appropriate amount of data).

推荐答案

可以执行多个步骤来获得更好的结果.而且不需要CNN或某些复杂的功能匹配,让我们尝试使用非常基本的方法来解决此问题.

There are multiple steps which can be performed to get better results. And there is no need of a CNN or some complex feature matching, lets try to solve this using very basic approached.

这可以通过紧密裁剪输入轮廓,然后将所有图像调整为相同的高度或宽度来完成.我将在这里选择宽度,比方说300px.让我们为此定义一个实用方法:

This can be done by closely cropping the input contour and then resize all the images either to same height or width. I will chose width here, let's say 300px. Let's define a utility method for this:

def normalize_contour(img):
    im, cnt, _ = cv2.findContours(img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    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]]

    new_height = int((1.0 * img.shape[0])/img.shape[1] * 300.0)
    img_resized = cv2.resize(img_cropped_bounding_rect, (300, new_height))
    return img_resized

此代码段将返回固定宽度为300的裁剪良好的轮廓.将此方法应用于所有数据库图像以及输入查询图像.

This code snippet would return a nicely cropped contour with a fixed width of 300. Apply this method to all the database images and input query image as well.

由于我们已将输入图像标准化为300像素,因此我们可以拒绝所有高度不接近标准化图像高度的候选对象.这将排除5PinDIN.

Since we have normalized the input image to 300 px we can reject all the candidates whose height is not close to the normalized image height. This will rule out 5PinDIN.

现在,您可以尝试以最大重叠度对结果进行排序,可以通过 cv2.contourArea()获取轮廓区域,并对所有其余候选进行排序以获取最接近的匹配项.

Now you can try sorting the results with max overlap, you can cv2.contourArea() to get the contour area and sort all the remaining candidates to get the closest possible match.

这篇关于两个相似形状之间的OpenCV形状匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆