重映射与SURF特征点检测与匹配
来源:互联网 发布:iphone8怎么卸载软件 编辑:程序博客网 时间:2024/06/06 13:04
一、重映射
1.1、简介
重映射在图像处理中主要的功能为:将一个图像中一个位置的像素放置到另一个图像指定位置的过程,可以根据自己设定的函数将图像进行变换,较常见的功能有关于x轴翻转,关于y轴翻转,关于x、y轴翻转。为了完成映射过程,有必要获得一些插值为非整数像素坐标,因为源图像与目标图像的像素坐标不是一一对应的。在实际应用中,我们通过重映射来表达每个像素的位置 (x,y),转换关系如下图所示 :
其中 g( ) 是目标图像, f( ) 是源图像, h(x,y) 是作用于 (x,y) 的映射方法函数。在openCV中是通过 remap( )函数来实现重映射功能。
1.2、remap( )函数解析
remap( )函数的原型和参数如下:
C++: void remap(InputArray src, OutputArraydst, InputArray map1, InputArray map2, int interpolation, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar( ) )
参数解析:
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位或者浮点型图像。
第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放函数调用后的输出结果,和源图片有一样的尺寸和类型。
第三个参数,InputArray类型的map1,它有两种可能的表示对象。
(1)表示点(x,y)的第一个映射。
(2)表示CV_16SC2 , CV_32FC1 或CV_32FC2类型的X值。
第四个参数,InputArray类型的map2,同样,它也有两种可能的表示对象,而且它是根据map1来确定表示那种对象。
(1)若map1表示点(x,y)时。这个参数不代表任何值。
(2)表示CV_16UC1 , CV_32FC1类型的Y值(第二个值)。
第五个参数,int类型的interpolation,插值方式,之前的resize( )函数中有讲到,需要注意,resize( )函数中提到的INTER_AREA插值方式在这里是不支持的,所以可选的插值方式如下:
(1)INTER_NEAREST - 最近邻插值;
(2)INTER_LINEAR – 双线性插值(默认值);
(3)INTER_CUBIC – 双三次样条插值(逾4×4像素邻域内的双三次插值);
(4)INTER_LANCZOS4 -Lanczos插值(逾8×8像素邻域的Lanczos插值)。
第六个参数,int类型的borderMode,边界模式,有默认值BORDER_CONSTANT,表示目标图像中“离群点(outliers)”的像素值不会被此函数修改。
第七个参数,const Scalar&类型的borderValue,当有常数边界时使用的值,其有默认值Scalar( ),即默认值为0。
1.3、重映射实例
1、代码
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace cv;int main(){ //【0】变量定义 Mat srcImage, dstImage; Mat map_x, map_y; //【1】载入原始图 srcImage = imread("1.jpg", 1); if (!srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; } imshow("原始图", srcImage); //【2】创建和原始图一样的效果图,x重映射图,y重映射图 dstImage.create(srcImage.size(), srcImage.type()); map_x.create(srcImage.size(), CV_32FC1); map_y.create(srcImage.size(), CV_32FC1); //【3】双层循环,遍历每一个像素点,改变map_x & map_y的值 for (int j = 0; j < srcImage.rows; j++) { for (int i = 0; i < srcImage.cols; i++) { //改变map_x & map_y的值. map_x.at<float>(j, i) = static_cast<float>(srcImage.cols-i); map_y.at<float>(j, i) = static_cast<float>(j); } } //【4】进行重映射操作 remap(srcImage, dstImage, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0)); //【5】显示效果图 imshow("【程序窗口】", dstImage); waitKey(); return 0;}
2、运行结果
(1)原图
(2)重映射效果图
二、利用SURF算法进行特征点检测
2.1、SURF算法简介
Speeded Up Robust Features(SURF,加速稳健特征)是一种稳健的局部特征点检测和描述算法。最初由Herbert Bay发表在2006年的欧洲计算机视觉国际会议(Europen Conference on Computer Vision,ECCV)上,并在2008年正式发表在Computer Vision and Image Understanding期刊上。
Surf是对David Lowe在1999年提出的Sift算法的改进,提升了算法的执行效率,为算法在实时计算机视觉系统中应用提供了可能。与Sift算法一样,Surf算法的基本路程可以分为三大部分:局部特征点的提取、特征点的描述、特征点的匹配。但Surf在执行效率上有两大制胜法宝——一个是积分图在Hessian(黑塞矩阵)上的使用,一个是降维的特征描述子的使用。一般来说,标准的SURF算子比SIFT算子快好几倍,并且在多幅图片下具有更好的稳定性。
Surf改进了Sift算法的特征提取和描述方式,用一种更为高效的方式完成特征的提取和描述,具体实现流程如下:
(1) 构建Hessian(黑塞矩阵),生成所有的兴趣点,将其用于特征的提取;
(2)构建尺度空间;
(3) 特征点定位;
(4)特征点主方向分配;
(5) 生成特征点描述子;
(6)特征点匹配。
2.2、drawKeypoints( )函数解析
void drawKeypoints(const Mat&image, const vector<KeyPoint>& keypoints, constScalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT )
第一个参数,const Mat&类型的src,输入图像。
第二个参数,const vector&类型的keypoints,根据源图像得到的特征点,它是一个输出参数。
第三个参数,Mat&类型的outImage,输出图像,其内容取决于第五个参数标识符falgs。
第四个参数,const Scalar&类型的color,关键点的颜色,有默认值Scalar::all(-1)。
第五个参数,int类型的flags,绘制关键点的特征标识符,有默认值DrawMatchesFlags::DEFAULT。可以选取别的值。
2.3、SURF特征点检测实例
1、下面实现特征点的功能需要用到下面几点:
(1)使用 FeatureDetector 接口来发现感兴趣点;
(2)使用 SurfFeatureDetector 以及其函数 detect 来实现检测过程;
(3)使用函数 drawKeypoints 绘制检测到的关键点。
2、代码
#include "opencv2/core/core.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/nonfree/nonfree.hpp" #include <iostream> using namespace cv;int main(int argc, char** argv){ //【0】改变console字体颜色 system("color 2F"); //【1】载入源图片并显示 Mat srcImage1 = imread("1.jpg", 1); Mat srcImage2 = imread("2.jpg", 1); if (!srcImage1.data || !srcImage2.data)//检测是否读取成功 { printf("读取图片错误,请确定目录下是否有imread函数指定名称的图片存在~! \n"); return false; } imshow("原始图1", srcImage1); imshow("原始图2", srcImage2); //【2】定义需要用到的变量和类 int minHessian = 400;//定义SURF中的hessian阈值特征点检测算子 SurfFeatureDetector detector(minHessian);//定义一个SurfFeatureDetector(SURF) 特征检测类对象 std::vector<KeyPoint> keypoints_1, keypoints_2;//vector模板类是能够存放任意类型的动态数组,能够增加和压缩数据 //【3】调用detect函数检测出SURF特征关键点,保存在vector容器中 detector.detect(srcImage1, keypoints_1); detector.detect(srcImage2, keypoints_2); //【4】绘制特征关键点 Mat img_keypoints_1; Mat img_keypoints_2; drawKeypoints(srcImage1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT); drawKeypoints(srcImage2, keypoints_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT); //【5】显示效果图 imshow("特征点检测效果图1", img_keypoints_1); imshow("特征点检测效果图2", img_keypoints_2); waitKey(0); return 0;}
3、运行结果
(1)原图
(2)特征点检测效果
三、SURF特征点匹配
3.1、FLANN匹配算法简介
FLANN (Fast_Library_for_Approximate_Nearest_Neighbors)意为快速最近邻搜索包。它是一个对大数据集和高维特征进行最近邻搜索的算法的集合,而且这些算法都已经被优化过了。在面对大数据集时它的效果要好于 BFMatcher。 经验证,FLANN比其他的最近邻搜索软件快10倍。
3.2、代码
///SURF特征点匹配 #include "opencv2/opencv.hpp" using namespace cv;#include "opencv2/nonfree/nonfree.hpp"//SURF相关 #include "opencv2/legacy/legacy.hpp"//匹配器相关 #include <iostream> using namespace std;int main(){ //1.SURF特征点提取——detect()方法 Mat srcImg1 = imread("1.jpg", CV_LOAD_IMAGE_COLOR); Mat srcImg2 = imread("2.jpg", CV_LOAD_IMAGE_COLOR); Mat dstImg1, dstImg2; //定义SURF特征检测类对象 SurfFeatureDetector surfDetector;//SurfFeatureDetector是SURF类的别名 //定义KeyPoint变量 vector<KeyPoint> keyPoints1; vector<KeyPoint> keyPoints2; //特征点检测 surfDetector.detect(srcImg1, keyPoints1); surfDetector.detect(srcImg2, keyPoints2); //绘制特征点(关键点) drawKeypoints(srcImg1, keyPoints1, dstImg1); drawKeypoints(srcImg2, keyPoints2, dstImg2); //显示结果 imshow("dstImg1", dstImg1); imshow("dstImg2", dstImg2); //2.特征点描述符(特征向量)提取——compute()方法 SurfDescriptorExtractor descriptor;//SurfDescriptorExtractor是SURF类的别名 Mat description1; Mat description2; descriptor.compute(srcImg1, keyPoints1, description1); descriptor.compute(srcImg2, keyPoints2, description2); //3.使用Flann匹配器进行匹配——FlannBasedMatcher类的match()方法 FlannBasedMatcher matcher;//实例化Flann匹配器 vector<DMatch> matches; matcher.match(description1, description2, matches); //4.对匹配结果进行筛选(依据DMatch结构体中的float类型变量distance进行筛选) float minDistance = 100; float maxDistance = 0; for (int i = 0; i < matches.size(); i++) { if (matches[i].distance < minDistance) minDistance = matches[i].distance; if (matches[i].distance > maxDistance) maxDistance = matches[i].distance; } cout << "minDistance: " << minDistance << endl; cout << "maxDistance: " << maxDistance << endl; vector<DMatch> goodMatches; for (int i = 0; i < matches.size(); i++) { if (matches[i].distance < 2 * minDistance) { goodMatches.push_back(matches[i]); } } //5.绘制匹配结果——drawMatches() Mat dstImg3; drawMatches(srcImg1, keyPoints1, srcImg2, keyPoints2, goodMatches, dstImg3); imshow("dstImg3", dstImg3); waitKey(0); return 0;}
3.3、运行结果
(1)原图
(2)特征匹配结果
- 重映射与SURF特征点检测与匹配
- Surf特征点检测与匹配
- Surf算法特征点检测与匹配
- Surf算法特征点检测与匹配
- opencv重映射&surf特征点检测
- Surf特征点检测与匹配代码分析
- Surf特征点检测与匹配代码分析
- OpenCV 重映射 & SURF特征点检测合辑
- SURF特征点检测与匹配之误匹配点删除
- SURF特征点检测与匹配之误匹配点删除
- 【OpenCV学习笔记】三十八、特征检测与匹配(三)——SURF特征点检测与匹配
- OpenCV中feature2D学习——FAST特征点检测与SIFT/SURF/BRIEF特征提取与匹配
- Java基于OpenCV的Surf特征检测与匹配
- Surf特征提取与匹配
- OpenCV中SURF特征点检测原理与实现
- surf与sift特征点检测代码实现
- 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- Hadoop 和 spark 读取多个文件通配符规则(正则表达式)joe
- HBASE 原理
- Alpha Beta RC GA RTM OEM RVL EVAL RTL 软件版本
- SPICE电路仿真(1)--ngspice
- java数据库
- 重映射与SURF特征点检测与匹配
- Java面试宝典-2
- centos 解决/usr/bin/ld: cannot find -lfl 问题。
- opencv学习笔记--形态学操作
- 卫星热分析
- Linux系统调用
- 112删除排序链表中的重复元素
- POJ 1125 Stockbroker Grapevine
- 微信发个朋友圈没有想到也可以用设计模式来实现——观察者模式