基于SURF特征的图像与视频拼接技术的研究和实现(一)

时间:2023-02-22 00:12:47
基于SURF特征的图像与视频拼接技术的研究和实现(一)
     一直有计划研究实时图像拼接,但是直到最近拜读西电2013年张亚娟的《基于SURF特征的图像与视频拼接技术的研究和实现》,条理清晰、内容完整、实现的技术具有市场价值。因此定下决心以这篇论文为基础脉络,结合实际情况,进行“基于SURF特征的图像与视频拼接技术的研究和实现”。
      一、基于opencv的surf实现
      3.0以后,surf被分到了"opencv_contrib-master"中去,操作起来不习惯,这里仍然选择一直在使用的opencv2.48,其surf的调用方式为:
 );
    Mat img_2  );
    ; }
    ;
    SurfFeatureDetector detector( minHessian );
    std), DrawMatchesFlags), DrawMatchesFlags);
    ;
}
这里采用的是surffeaturedector的方法进行点的寻找,而后采用BFMatcher的方法进行数据比对。但这种方法错误的比较多,提供了FLANN的方法进行比对:
 );
    Mat img_2  );
    ; }
    ;
    SurfFeatureDetector detector( minHessian );
    std), DrawMatchesFlags), DrawMatchesFlags; ;
    ; i ; i .) )
    { good_matches.push_back( matches[i]); }
    }
    ), Scalar),
        vector; i );
    ;
}
 
 
基于SURF特征的图像与视频拼接技术的研究和实现(一)
可以发现,除了错误一例,其他都是正确的。
继续来做,计算出单应矩阵
 );
    Mat img_2  );
    ; }
    ;
    SurfFeatureDetector detector( minHessian );
    std), DrawMatchesFlags), DrawMatchesFlags; ;
    ; i ; i ), Scalar),
        vector; i );
    obj_corners[] ,); obj_corners[]  );
    obj_corners[] ] , img_1.rows );
    std);
    perspectiveTransform( obj_corners, scene_corners, H);
    );
    line( img_matches, scene_corners[] ] , , ),  );
    line( img_matches, scene_corners[] ] , , ),  );
    line( img_matches, scene_corners[] ] , , ),  );
    line( img_matches, scene_corners[] ] , , ),  );
    );
    ;
}
 
 
基于SURF特征的图像与视频拼接技术的研究和实现(一)
简化后和注释后的版本
// raw_surf.cpp : 本例是对opencv-2.48相关例子的实现
//
 
#include "stdafx.h"
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/nonfree/features2d.hpp"
#include "opencv2/calib3d/calib3d.hpp"
using namespace std;
using namespace cv;
 
int main( int argc, char** argv )
{
 
    Mat img_1 = imread( "img_opencv_1.png", 0 );
    Mat img_2 = imread( "img_opencv_2.png", 0 );
    if( !img_1.data || !img_2.data )
    { std::cout<< " --(!) Error reading images " << std::endl; return -1; }
 
    //-- Step 1: 使用SURF识别出特征点
    int minHessian = 400;
    SurfFeatureDetector detector( minHessian );
    std::vector<KeyPoint> keypoints_1, keypoints_2;
    detector.detect( img_1, keypoints_1 );
    detector.detect( img_2, keypoints_2 );
    //-- Step 2: 描述SURF特征
    SurfDescriptorExtractor extractor;
    Mat descriptors_1, descriptors_2;
    extractor.compute( img_1, keypoints_1, descriptors_1 );
    extractor.compute( img_2, keypoints_2, descriptors_2 );
    //-- Step 3: 匹配
    FlannBasedMatcher matcher;//BFMatcher为强制匹配
    std::vector< DMatch > matches;
    matcher.match( descriptors_1, descriptors_2, matches );
    //取最大最小距离
    double max_dist = 0; double min_dist = 100;
    for( int i = 0; i < descriptors_1.rows; i++ )
    { 
        double dist = matches[i].distance;
        if( dist < min_dist ) min_dist = dist;
        if( dist > max_dist ) max_dist = dist;
    }
    std::vector< DMatch > good_matches;
    for( int i = 0; i < descriptors_1.rows; i++ )
    { 
        if( matches[i].distance <= 3*min_dist )//这里的阈值选择了3倍的min_dist
            { 
                good_matches.push_back( matches[i]); 
             }
    }
    //画出"good match"
    Mat img_matches;
    drawMatches( img_1, keypoints_1, img_2, keypoints_2,
        good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
        vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
    //-- Localize the object from img_1 in img_2
    std::vector<Point2f> obj;
    std::vector<Point2f> scene;
    for( int i = 0; i < (int)good_matches.size(); i++ )
    {    
        obj.push_back( keypoints_1[ good_matches[i].queryIdx ].pt );
        scene.push_back( keypoints_2[ good_matches[i].trainIdx ].pt );
    }
    //直接调用ransac,计算单应矩阵
    Mat H = findHomography( obj, scene, CV_RANSAC );
    //-- Get the corners from the image_1 ( the object to be "detected" )
    std::vector<Point2f> obj_corners(4);
    obj_corners[0] = Point(0,0); 
    obj_corners[1] = Point( img_1.cols, 0 );
    obj_corners[2] = Point( img_1.cols, img_1.rows ); 
    obj_corners[3] = Point( 0, img_1.rows );
    std::vector<Point2f> scene_corners(4);
    perspectiveTransform( obj_corners, scene_corners, H);
    //-- Draw lines between the corners (the mapped object in the scene - image_2 )
    Point2f offset( (float)img_1.cols, 0);
    line( img_matches, scene_corners[0] + offset, scene_corners[1] + offset, Scalar(0, 255, 0), 4 );
    line( img_matches, scene_corners[1] + offset, scene_corners[2] + offset, Scalar( 0, 255, 0), 4 );
    line( img_matches, scene_corners[2] + offset, scene_corners[3] + offset, Scalar( 0, 255, 0), 4 );
    line( img_matches, scene_corners[3] + offset, scene_corners[0] + offset, Scalar( 0, 255, 0), 4 );
    //-- Show detected matches
    imshow( "Good Matches & Object detection", img_matches );
    waitKey(0);
    return 0;
}
 
 
 
 
基于SURF特征的图像与视频拼接技术的研究和实现(一)
这里有两点需要注意,一个是除了FlannBasedMatcher之外,还有一种mathcer叫做BFMatcher,后者为强制匹配.
此外计算所谓GOODFEATURE的时候,采用了 3*min_dist的方法,我认为这里和论文中指出的“误差阈值设为3”是一致的,如果理解错误请指出,感谢!
同时测试了航拍图片和连铸图片,航拍图片是自然图片,特征丰富;
基于SURF特征的图像与视频拼接技术的研究和实现(一)
连铸图片由于表面干扰大于原始纹理,无法得到单应矩阵
基于SURF特征的图像与视频拼接技术的研究和实现(一)
基于SURF特征的图像与视频拼接技术的研究和实现(一)
        最后,添加计算RANSAC内点外点的相关代码,这里以3作为分界线
       // raw_surf.cpp : 本例是对opencv-2.48相关例子的实现
 );
    Mat img_2  );
    ; }
    ;
    SurfFeatureDetector detector( minHessian );
    std; ;
    ; i ; i ), Scalar),
        vector; i );
    obj_corners[] ,); 
    obj_corners[]  );
    obj_corners[] ] , img_1.rows );
    std);
    perspectiveTransform( obj_corners, scene_corners, H);
    ;i,fDistance(scene[i],scene_test[i]));
    }
    
    );
    line( img_matches, scene_corners[] ] , , ),  );
    line( img_matches, scene_corners[] ] , , ),  );
    line( img_matches, scene_corners[] ] , , ),  );
    line( img_matches, scene_corners[] ] , , ),  );
    );
    ;
}
 
 
        结果显示
基于SURF特征的图像与视频拼接技术的研究和实现(一)
       其中,有误差的点就很明显了。
       小结一下,这里实现了使用opencv得到两幅图像之间的单应矩阵的方法。不是所有的图像都能够获得单应矩阵的,必须是两幅本身就有关系的图片才可以;而且最好是自然图像,像生产线上的这种图像,其拼接就需要采用其他方法。
二、拼接和融合
        由于之前已经计算出了“单应矩阵”,所以这里直接利用这个矩阵就好。需要注意的一点是理清楚“帧”和拼接图像之间的关系。一般来说,我们采用的是“柱面坐标”或平面坐标。书中采用的是若干图像在水平方向上基本上是一字排开,是平面坐标。那么,如果按照文中的“帧到拼接图像”的方法,我们认为图像拼接的顺序就是由左到右,一幅一幅地计算误差,而后进行叠加。
         为了方便说明算法,采用了《学习opencv》中提供的教堂图像
基于SURF特征的图像与视频拼接技术的研究和实现(一)
基于SURF特征的图像与视频拼接技术的研究和实现(一)
其结果就是经过surf匹配,而将右边的图像形变成为适合叠加的状态。
基于此,进行图像对准
;
    SurfFeatureDetector detector( minHessian );
    std; ;
    ; i ; i ; i ,,img_2.cols,img_2.rows));
    img_raw_1.copyTo(half);
    imshow();
    ;
}
 
 
基于SURF特征的图像与视频拼接技术的研究和实现(一)
依据论文中提到的3种方法进行融合
;
    SurfFeatureDetector detector( minHessian );
    std; ;
    ; i ; i ; i ,,img_2.cols,img_2.rows));
    img_raw_1.copyTo(half);
    imshow(.;
     ;
     ;i;i.;
    }
    imshow(;i;j;j]]];
            ]]];
            ;i;j;j]]];
            ]]];
            )
            {
                result_advance.at;i;j;j]]];
            ]]];
            ]]];
            )
            {
                result_advance.at;i;j;j]]];
            ]]];
            )
            {
                result_advance.at);
    ;
}
 
 
基于SURF特征的图像与视频拼接技术的研究和实现(一)
基于SURF特征的图像与视频拼接技术的研究和实现(一)
基于SURF特征的图像与视频拼接技术的研究和实现(一)
基于SURF特征的图像与视频拼接技术的研究和实现(一)
目前看来,maxvalue是最好的融合方法,但是和论文中提到的一样,此类图片不能很好地体现融合算法的特点,为此我也拍摄了和论文中类似的图片。发现想拍摄质量较好的图片,还是需要一定的硬件和技巧的。因此,软件和硬件,在使用的过程中应该结合起来。
此外,使用文中图片,效果如下
基于SURF特征的图像与视频拼接技术的研究和实现(一)
基于SURF特征的图像与视频拼接技术的研究和实现(一)
基于SURF特征的图像与视频拼接技术的研究和实现(一)
基于SURF特征的图像与视频拼接技术的研究和实现(一)
换一组图片,可以发现不同的结果
基于SURF特征的图像与视频拼接技术的研究和实现(一)
基于SURF特征的图像与视频拼接技术的研究和实现(一)
基于SURF特征的图像与视频拼接技术的研究和实现(一)
基于SURF特征的图像与视频拼接技术的研究和实现(一)
相比较而言,还是linerblend能够保持不错的质量,而具体到底采取哪种拼接的方式,必须根据实际情况来选择。
三、多图连续融合拼接
        前面处理的是2图的例子,至少将这种情况推广到3图,这样才能够得到统一处理的经验。
        连续图像处理,不仅仅是在已经处理好的图像上面再添加一幅图,其中比较关键的一点就是如何来处理已经拼接好的图像。
基于SURF特征的图像与视频拼接技术的研究和实现(一)
那么,m2也就是H.at<char>(0,2)就是水平位移。但是在实际使用中,始终无法正确取得这个值
基于SURF特征的图像与视频拼接技术的研究和实现(一)
Mat outImage );
    ];     ),Point(result_linerblend.cols,,),);
    imshow("result_linerblend",result_linerblend);
只好采取编写专门代码的方法进行处理
;;;j;j,j)[])
        {
            idaterow0 ;j;j,j)[])
        {
            idaterowend ),Point(min(idaterow0,idaterowend),img_2.rows),Scalar(,,),);
    imshow("result_linerblend",matmask);
基于SURF特征的图像与视频拼接技术的研究和实现(一)
效果良好稳定.目前的实现是将白线以左的区域切割下来进行拼接。
基于此,编写3图拼接,效果如下。目前的图像质量,在差值上面可能还需要增强,下一步处理
基于SURF特征的图像与视频拼接技术的研究和实现(一)
;
    SurfFeatureDetector detector( minHessian );
    std; ;
    ; i ; i ; i ,,img_2.cols,img_2.rows));
    img_raw_1.copyTo(half);
    .;
    ;
    ;i;i.;
    }
    ;;;j;j,j)[])
        {
            idaterow0 ;j;j,j)[])
        {
            idaterowend ),Point(min(idaterow0,idaterowend),img_2.rows),Scalar(,,),);
    imshow(,,min(idaterow0,idaterowend),img_2.rows));
    img_raw_2 ;  min_dist ;
    ; i ; i ; i ,,img_1.cols,img_1.rows));
    img_raw_1.copyTo(half2);
    imshow(.;
     ioffset ;
    ;i;i.;
    }
    imshow();
    ;
}
 
 
复制粘贴,实现5图拼接。这个时候发现,3图往往是一个极限值(这也可能就是为什么opencv里面的例子提供的是3图),当第四图出现的时候,其单应效果非常差
基于SURF特征的图像与视频拼接技术的研究和实现(一)
为什么会出现这种情况,反思后认识到,论文中采用的是平面坐标,也就是所有的图片都是基本位于一个平面上的,这一点特别通过她后面的那个罗技摄像头的部署能够看出来。但是在现实中,更常见的情况是人站在中间,360度地拍摄,这个时候需要采用柱面坐标系,也就是一开始对于图像要进行相关处理,也就是所谓的柱状投影。
基于SURF特征的图像与视频拼接技术的研究和实现(一)
可以得到这样的效果,这个效果是否正确还有待商榷,但是基于此的确可以更进一步地做东西了。
.
 
;i;j;
        }
    }
    
    ));
    ;
    ;
    ;
    ;i;j) ) ))
            {
                img_result.at);
    ;
}
 
 
 
基于SURF特征的图像与视频拼接技术的研究和实现(一)
效果依然是不佳,看来在这个地方,不仅仅是做一个桶形变换那么简单,一定有定量的参数在里面,也可能是我的变换写错了。这个下一步研究。
【未完待续】
 
 
 

基于SURF特征的图像与视频拼接技术的研究和实现(一)的更多相关文章

  1. paper 116:自然图像抠图&sol;视频抠像技术梳理(image matting&comma; video matting)

    1. Bayesian Matting, Chuang, CVPR 2001.http://grail.cs.washington.edu/projects/digital-matting/paper ...

  2. 2个YUV视频拼接技术

    http://blog.csdn.net/huahuahailang/article/details/9040847 2个YUV视频拼接技术 http://zhongcong386.blog.163. ...

  3. Opencv Sift和Surf特征实现图像无缝拼接生成全景图像

    Sift和Surf算法实现两幅图像拼接的过程是一样的,主要分为4大部分: 1. 特征点提取和描述 2. 特征点配对,找到两幅图像中匹配点的位置 3. 通过配对点,生成变换矩阵,并对图像1应用变换矩阵生 ...

  4. 基于SURF特征的目标检测

    转战matlab了.步骤说一下: 目标图obj 含目标的场景图scene 载入图像 分别检测SURF特征点 分别提取SURF描述子,即特征向量 用两个特征相互匹配 利用匹配结果计算两者之间的trans ...

  5. Opencv中使用Surf特征实现图像配准及对透视变换矩阵H的平移修正

    图像配准需要将一张测试图片按照第二张基准图片的尺寸.角度等形态信息进行透视(仿射)变换匹配,本例通过Surf特征的定位和匹配实现图像配准. 配准流程: 1. 提取两幅图像的Surf特征 2. 对Sur ...

  6. 图像处理之基础---2个YUV视频 拼接技术

    /************************************************* * 主要功能:两路 YUV4:2:0拼接一路左右半宽格式YUV视频 参考资料:http://www ...

  7. OpenCV Using Python——基于SURF特征提取和金字塔LK光流法的单目视觉三维重建 &lpar;光流、场景流&rpar;

    https://blog.csdn.net/shadow_guo/article/details/44312691 基于SURF特征提取和金字塔LK光流法的单目视觉三维重建 1. 单目视觉三维重建问题 ...

  8. paper 27 :图像&sol;视觉显著性检测技术发展情况梳理&lpar;Saliency Detection、Visual Attention)

    1. 早期C. Koch与S. Ullman的研究工作. 他们提出了非常有影响力的生物启发模型. C. Koch and S. Ullman . Shifts in selective visual ...

  9. 基于 IJKPlayer-concat 协议的视频无缝拼接技术实现

    一.前言 Hi,大家好,我是承香墨影! 开门见山,开篇名义.今天来聊聊如何将多段视频,拼接成一个完整而连续的视频,然后无缝进行播放. 这样的需求应该不算偏门吧? 最简单的就是一些视频 App,会将大段 ...

随机推荐

  1. 前端:js

    JavaScript: 参考文章: http://www.cnblogs.com/wupeiqi/articles/5369773.html http://javascript.ruanyifeng. ...

  2. web&period;xml配置error-page

    一. 通过错误码来配置error-page <error-page> <error-code>404</error-code> <location>/e ...

  3. Android Service使用拾遗&lbrack;阿里工程师分享&rsqb;

    Service作为android的四大组件之一常用来帮助我们完成一些需要放在后台处理的任务,通过startService和bindService两种方式被调用.因为Service也是在主线程中运行的, ...

  4. listview向下滑动过程中背景色变成黑色和一些奇怪问题

    ListView是一个经常要用到的android控件,现总结遇到过的一些美化的小细节. 1.listview在拖动的时候背景图片消失变成黑色背景,等到拖动完毕我们自己的背景图片才显示出来 这个问题是我 ...

  5. c&plus;&plus;11之右值引用

    本文大部分来自这里,并不是完全着行翻译,如有不明白的地方请参考原文. 在c++中,创建临时对象的开销对程序的影响一直很大,比如以下这个例子: String getName(){ return “Kia ...

  6. oracle获取本月第一天和最后一天及Oracle trunc&lpar;&rpar;函数的用法

    select to_char(trunc(add_months(last_day(sysdate), -1) + 1), 'yyyy-mm-dd') "本月第一天", to_cha ...

  7. 判断&amp&semi;数学&amp&semi;生活

    作者:黄永刚 初次接触<概率论与数理统计>这门课的时候,脑袋中只有三个词:黑球.白球.袋子,所有的课程内容就是先取,后取,接触一月之后成功的被放趴下了,因此对于这门课程是没有什么好感的,考 ...

  8. Accounting Flexfield Setup and Usage &lpar;Doc ID 124333&period;1&rpar;

    APPLIES TO:Oracle General Ledger - Version 11.5.10.2 to 12.1.3 [Release 11.5.10 to 12.1] Information ...

  9. 初级字典树查找在 Emoji、关键字检索上的运用 Part-1

    系列索引 Unicode 与 Emoji 字典树 TrieTree 与性能测试 生产实践 前言 通常用户自行修改资料是很常见的需求,我们规定昵称长度在2到10之间.假设用户试图使用表情符号 ‍

  10. SQL中SELECT INTO和INSERT INTO SELECT语句介绍

    表复制是经常要用到的操作,下面就将为您介绍SQL中SELECT INTO和INSERT INTO SELECT语句,供您参考. Insert是T-sql中常用语句,Insert INTO table( ...