首页 > 解决方案 > ORB+BFMatcher 是否适合识别重复图像(有细微的变化?)

问题描述

我需要识别具有已知值的手写数字的图像。带有数字的物理对象始终相同,但位置/比例/照明略有不同。它们的数量约为 100,大小约为 100x500 像素。

在第一遍中,代码应该“学习”可能的输入,然后在它们再次出现时识别它们(将它们分类为接近“训练”图像之一)。

我主要关注的是特征匹配 Python-OpenCV 教程

首先分析输入图像,在orbTrained列表中记住关键点和描述符:

import cv2
import collections

ORBTrained=collections.namedtuple('ORBTrained',['kp','des','img'])
orbTrained=[]

for img in trainingImgs:
    z2=preprocessImg(img)
    orb=cv2.ORB_create(nfeatures=400,patchSize=30,edgeThreshold=0)
    kp,des=orb.detectAndCompute(z2,None)
    orbTrained.append(ORBTrained(kp=kp,des=des,img=z2))
    z3=cv2.drawKeypoints(z2,kp,None,color=(0,255,0),flags=0)

第一阶段的典型结果如下所示:

示例训练图像

然后在下一个循环中,对于每个真实输入图像,循环遍历所有训练图像以查看哪个匹配最佳:

ORBMatch=collections.namedtuple('ORBMatch',['dist','match','train'])
for img in inputImgs:
    z2=preprocessNum(img)
    orb=cv2.ORB_create(nfeatures=400,patchSize=30,edgeThreshold=0)
    kp,des=orb.detectAndCompute(z2,None)
    bf=cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck=True)
    mm=[]
    for train in orbTrained:
        m=bf.match(des,train.des)
        dist=sum([m_.distance for m_ in m])
        mm.append(ORBMatch(dist=dist,match=m,train=train))
    # sort matching images based on score
    mm.sort(key=lambda m: m.dist)
    print([m.dist for m in mm[:5]])
    best=mm[0]
    best.match.sort(key=lambda x:x.distance) # sort matches in the best match
    z3=cv2.drawMatches(z2,kp,best.train.img,best.train.kp,best.match[:50],None,flags=2)

我得到的结果是荒谬的,并且始终如此(仅当我使用像素相同的输入运行时,结果才是正确的):

样本匹配

问题是什么?我完全误解了该怎么做,还是我只需要调整一些参数?

标签: opencvclassificationmatchingorb

解决方案


首先,您确定不是通过创建自己的 OCR 库来重新发明轮子吗?有许多免费框架,其中一些支持使用自定义字符集进行训练。

其次,你应该明白什么是特征匹配。它会找到类似的小区域,但不知道其他特征对。它将匹配字符的相似角,而不是字符本身。您可以尝试使用更大的patchSize,以便它覆盖至少一半的数字。

您可以通过一次仅对单个数字运行特征检测来最小化错误对,使用阈值和轮廓来查找字符边界。

如果文本未旋转,则使用诸如 ORB 之类的旋转不变特征描述符不是最佳选择,请尝试使用旋转变量描述符,例如FAST


推荐阅读