我正在尝试将稍微不规则的形状与形状数据库匹配。例如,在这里我要匹配的轮廓:
有关更多信息,这是HDMI连接器的轮廓,以轮廓表示。这有点粗糙,因为这是在握住HDMI时用手机拍摄的。
这是我的连接器数据库:
这些轮廓更加清晰,因为这些轮廓是从互联网的连接器图像中收集的。
对于我尝试过的:
cv2.matchShapes()
由于这些都是轮廓,因此我尝试使用matchShapes()方法直接比较它们,但结果不佳。不规则轮廓与我的数据库之间的相似之处是:
HDMI:0.90
DB25:0.84
5 DIN针:0.5
DVI:0.21
由于匹配结果越接近0,轮廓越相似,该算法完全失败。我通过更改第三个参数尝试了其他匹配方法,但仍然没有成功。
ORB:
与SIFT类似,我尝试了关键点匹配。在数据库中平均不同匹配项之间的距离(找到匹配项的前15%之后):
mean([m.distance for m in matches])
距离为:
五针DIN:7.6
DB25:11.7
DVI:12.1
HDMI:19.6
由于这将圆形归类为最像我的轮廓的形状,因此也失败了。
以下是实际HDMI插槽与我的示例HDMI插槽的ORB匹配的关键点,以获取更多信息:
有什么想法/其他算法应该尝试吗?还是CNN是我唯一的选择(我宁愿避免使用它,因为我没有足够的数据量)。
可以执行多个步骤以获得更好的结果。并且不需要CNN或某些复杂的功能匹配,让我们尝试使用非常基本的方法来解决此问题。
可以通过仔细裁剪输入轮廓,然后将所有图像调整为相同的高度或宽度来实现。我将在这里选择宽度,比方说300px。让我们为此定义一个实用程序方法:
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的裁剪好的轮廓。将此方法应用于所有数据库图像以及输入的查询图像。
由于我们已将输入图像标准化为300像素,因此我们可以拒绝所有高度不接近标准化图像高度的候选图像。这将排除5PinDIN。
现在,您可以尝试对具有最大重叠量的结果进行排序,可以cv2.contourArea()
获取轮廓区域,并对所有剩余的候选对象进行排序,以获取最接近的匹配项。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句