1、读取图像
Mat img_1=imread(argv[1],CV_LOAD_IMAGE_COLOR);
//表示以彩色图像形式读取argv中的参数信息,并且存贮于img_1中
Mat img_2=imread(argv[2],CV_LOAD_IMAGE_COLOR);
//imread(const String & 文件名, int flags = 读取图片方式 ) 返回值:Mat类型
Mat(图像矩阵) 为 opencv 中的类 ,无需定义维度 ,自适应。另外,这里img_1和img_2存储了两张图像的颜色信息,其维度为2维,大小为480*640(这里存储数据的矩阵维度并非480*640,而是480*(640*3),因为要存储每个像素点的BGR信息,因此每个像素的信息对应1行和3列)。
imread函数
#include <opencv2/imgcodecs.hpp>
Mat cv::imread(const String &filename, int flags = IMREAD_COLOR )
imread函数原型非常简单,可以总结为三点
返回值:Mat 类型, 即返回读取的图像,读取图像失败时返回一个空的矩阵对象(Mat::data == NULL)
参数1 filename, 读取的图片文件名,可以使用相对路径或者绝对路径,但必须带完整的文件扩展名(图片格式后缀)
参数2 flags, 一个读取标记,用于选择读取图片的方式,默认值为1,flag值的设定与用什么颜色格式读取图片有关
图像类型有以下几种:
CV_LOAD_IMAGE_UNCHANGED——等价取值为-1,这个标识在新版本中已被废置,可以忽略
CV_LOAD_IMAGE_GRAYSCALE——等价取值为0,返回灰色图像
CV_LOAD_IMAGE_COLOR——等价取值为1,返回彩色图像
CV_LOAD_IMAGE_ANYDEPTH——等价取值为2,若图像深度是16位或者32位,就返回对应深度,否则,返回8位图像
如果输入有冲突的标志,将采用较小的数字值
2、初始化
std::vector<KeyPoint>keypoints_1,keypoints_2;
//容器vector类型<keypoint>图片1 -> 关键点1 图片2 -> 关键点2;
//存储角度 距离 分类 关键点坐标 金字塔层数等关键信息。
Mat descriptors_1,descriptors_2;
Ptr<ORB> orb=ORB::create(500,1.2f,8,31,0,2,ORB::HARRIS_SCORE,31,20);
第1步:检测Oriented FAST角点位置
orb->detect(img_1,keypoints_1);
orb->detect(img_2,keypoints_2);
第2步:根据角点位置计算BRIEF描述子
orb->compute(img_1,keypoints_1,descriptors_1);
orb->compute(img_2,keypoints_2,descriptors_2);
Mat outimg1;//Mat:图像矩阵构造函数
drawKeypoints(img_1,keypoints_1,outimg1,Scalar::all(-1),DrawMatchesFlags::DEFAULT);
imshow("ORB特征点",outimg1);
drawKeypoint函数:绘制图像
cv2.drawKeypoints(image, keypoints, outImage, color=None, flags=None)
image
原始图像,可以使三通道或单通道图像;keypoints
特征点向量,向量内每一个元素是一个KeyPoint对象,包含了特征点的各种属性信息;
outImage
特征点绘制的画布图像,可以是原图像;
color
绘制的特征点的颜色信息,默认绘制的是随机彩色; Scalar::all(-1) // 颜色随机
flags
特征点的绘制模式,其实就是设置特征点的那些信息需要绘制,那些不需要绘制,有以下几种模式可选:DEFAULT:只绘制特征点的坐标点,显示在图像上就是一个个小圆点,每个小圆点的圆心坐标都是特征点的坐标。
DRAW_OVER_OUTIMG:函数不创建输出的图像,而是直接在输出图像变量空间绘制,要求本身输出图像变量就是一个初始化好了的,size与type都是已经初始化好的变量
NOT_DRAW_SINGLE_POINTS:单点的特征点不被绘制DRAW_RICH_KEYPOINTS:绘制特征点的时候绘制的是一个个带有方向的圆,这种方法同时显示图像的坐标,size,和方向,是最能显示特征的一种绘制方式。
第3步:使用Hamming距离进行BRIEF描述子匹配
vector<DMatch>matches;
//DMatch是匹配关键点描述子 类, matches用于存放匹配项
BFMatcher matcher(NORM_HAMMING);
matcher.match(descriptors_1,descriptors_2,matches);
// 使用match方法,获取最匹配的两个特征点(匹配的特征点可以有多对,均存放在matche中)
第4步:匹配点筛选
double min_dist=10000,max_dist=0;
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;
}
printf("--Max dist:%f\n",max_dist);
printf("--Min dist:%f\n",min_dist);
std::vector<DMatch>good_matches;
for(int i=0;i<descriptors_1.rows;i++)
{
if(matches[i].distance<=max(2*min_dist,30.0))
{
good_matches.push_back(matches[i]);
}
}
第5步:绘制匹配结果
Mat img_match;//存放所有匹配点
Mat img_goodmatch; //存放好的匹配点
// drawMatches用于绘制两幅图像的匹配关键点
// 参数5是两张图像的匹配关键点数组,参数6用于存放函数的绘制结果
drawMatches(img_1,keypoints_1,img_2,keypoints_2,matches,img_match);
drawMatches(img_1,keypoints_1,img_2,keypoints_2,good_matches,img_goodmatch);
imshow("所有匹配点对",img_match);
imshow("优化后匹配点对",img_goodmatch);
waitKey(0);
return 0;
drawMatches()函数:绘制两幅图像的匹配关键点
// Draws matches of keypints from two images on output image.
void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
const Mat& img2, const vector<KeyPoint>& keypoints2,
const vector<vector<DMatch> >& matches1to2, Mat& outImg,
const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1),
const vector<vector<char> >& matchesMask=vector<vector<char> >(), int flags=DrawMatchesFlags::DEFAULT );
img1 – 源图像1
keypoints1 – 源图像1的特征点.
img2 – 源图像2.
keypoints2 – 源图像2的特征点
matches1to2 – 源图像1的特征点匹配源图像2的特征点[matches[i]] .
outImg – 输出图像具体由flags决定.
matchColor– 匹配的颜色(特征点和连线),若matchColor ==Scalar::all(-1),颜色随机.
singlePointColor – 单个点的颜色,即未配对的特征点,若matchColor ==Scalar::all(-1),颜色随机.
matchesMask –Mask决定哪些点将被画出,若为空,则画出所有匹配点.
flags – Fdefined by DrawMatchesFlags.
waitKey()函数
1.waitKey()与waitKey(0),都代表
无限等待
,waitKey函数的默认参数就是int delay = 0,故这俩形式本质是一样的。2.waitKey(n),等待
n毫秒
后,关闭显示的窗口。
3、编译
make完成后需要在终端键入图像的路径,绝对路径如图所示。
./工程名 绝对路径/1.png 绝对路径/2.png
例如我的工程名为feature_extraction:
./feature_extraction /home/ddd/slam14/feature_extraction/1.png /home/ddd/slam14/feature_extraction/2.png
参考链接:slambook2(ch7)—— orb_cv.cpp代码详解(ORB特征提取与匹配)_slambook2代码_@曾记否的博客-优快云博客