利用surf特征对票据做归一化

最近正在做一个票据识别归一化的项目,主要实现的功能是把图片归一化成跟模板一样的图片。
首先这边先说明下,这个算法适应图片的版面上有较多的不变特征,如果图片上有较多的不变特征,还可以用此算法做边框切割(算法有做透视变换,连透视变换都省了)。

例如:
这张是模板图片(模板是选用不变特征来做成的,这样会提高准确率,用标准一点的图片做模板也是可以的):
模板图片
这张是待归一化的图片:
原始图片
实现的功能是把待归一化的图片处理成与模板图片一样的图片(主要是为之后的切片),处理后的图片:
结果图片
这样就能把原始图片与模板图片每个像素点都对应上,方便之后的处理。

算法的具体流程:
1:surf特征的提取(如果特征点太多,会根据模板的特征点数进行一次原始图片的特征提取,主要是为了减少匹配的时间);


SurfFeatureDetector surfDetector(1000);   
    vector<KeyPoint> keyPoint1,keyPoint2;    
    surfDetector.detect(image1,keyPoint1);    
    surfDetector.detect(image2,keyPoint2); 

    if (keyPoint1.size() > keyPoint2.size() * 4)
    {
        keyPoint1.clear();
        SurfFeatureDetector surfDetector(3000);  
        surfDetector.detect(image1,keyPoint1);  
    }
    else if (keyPoint1.size() > keyPoint2.size() * 3)
    {
        keyPoint1.clear();
        SurfFeatureDetector surfDetector(2500); 
        surfDetector.detect(image1,keyPoint1);  
    }
    else if (keyPoint1.size() > keyPoint2.size() * 2.5)
    {
        keyPoint1.clear();
        SurfFeatureDetector surfDetector(2000);  
        surfDetector.detect(image1,keyPoint1);  
    }
    else if (keyPoint1.size() > keyPoint2.size() * 2)
    {
        keyPoint1.clear();
        SurfFeatureDetector surfDetector(1500);  
        surfDetector.detect(image1,keyPoint1);  
    }

2:特征点描述;

SurfDescriptorExtractor SurfDescriptor;
    Mat imageDesc1, imageDesc2;
    SurfDescriptor.compute(image1, keyPoint1, imageDesc1);
    SurfDescriptor.compute(image2, keyPoint2, imageDesc2);

3:根据FLANN匹配器进行匹配,并进行筛选;

FlannBasedMatcher matcher;
    vector< DMatch > matches;
    vector<vector<DMatch>> m_knnMatches;

    float minRatio = 1.f / 1.5f;
    matcher.knnMatch(imageDesc1,imageDesc2,m_knnMatches,2);  
    //sort(m_knnMatches.begin(),m_knnMatches.end()); //特征点排序 

    cout << "m_knnMatches个数:" << m_knnMatches.size() << endl;

    for (int i = 0; i<m_knnMatches.size(); i++)
    {
        float distanceRatio = m_knnMatches[i][0].distance / m_knnMatches[i][1].distance;
        //cout<<"distanceRatio:%f"<<distanceRatio<<endl;

        if (distanceRatio <= minRatio)
        {
            matches.push_back(m_knnMatches[i][0]);
        }
    }

    cout << "matches个数:" << matches.size() << endl;

4:根据筛选过的点求取变换矩阵;

“`
Mat homo = findHomography(imagePoints1, imagePoints2, CV_RANSAC);

5:这步是根据变换矩阵进行校验,校验函数judgeHome(&homo),这是自己写的函数,可以把矫正错的图片给筛选出来。

6:变换矩阵求出来后那只要透视变换就好了,我用的是 warpPerspective(yImage2, imageTransform1, homo, Size(mImage1.cols, mImage1.rows));

筛选匹配点后的图片:
这里写图片描述
在这边看图片上还是会有一小部分的特征匹配错了,不过对于大部分点有匹配对就想了,在求取变换矩阵是会选择正确的匹配点的,现在也有在做匹配点的筛选,还没完成就是了,findHomography会比较复杂点,大家有兴趣可以去看看。

改进方向:
1:建立多个模板,可以把模板的特征放在文件里,可以写多个模板进去,然后去匹配,找到最匹配的模板进行归一化,这样会提高准确率。
2:错误匹配点的去除也会提高准确率;
3:试了下用这样的算法去做证件类型的边框切割,感觉效果还可以(比如军官证,户口本之类的),接下来会尝试这方面的尝尝。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值