opencv实现最基本的图像配准
来源:互联网 发布:iphone写日记的软件 编辑:程序博客网 时间:2024/06/06 13:07
简介
本篇是对基于opencv实现图像配准的实现笔记。
基本原理
可以参考如下流程:
大致操作: 1、先拍摄两张有相同区域的图片,注意图片尺寸保持一致。 2、分别提取出图像的特征点(如果图像质量很差的话,可能需要先做些预处理操作)。 3、根据图像特征点,对它们做特征点匹配。 4、筛选出比较好的特征匹配点。 5、根据这些特征匹配点计算出畸变仿射矩阵。 6、使用算出来的矩阵进行图像匹配。
具体实现
特征点检测
可以参考如下资料:使用FLANN进行特征点匹配 核心的大致代码为:
- //-- Step 1: Detect the keypoints using SURF Detector
- int minHessian = 800;
- SurfFeatureDetector detector(minHessian );
- std::vector<KeyPoint> keypoints_1, keypoints_2;
- detector.detect(src1, keypoints_1);
- detector.detect(src2, keypoints_2);
- int i, count = 0;
src1和src2分别为配准测试图片,检测出来的图像特征点保存在:keypoints_1和keypoints_2中。注意结构:keypoints_1[i].pt.x和keypoints_1[i].pt.x :i表示当前为第几个特征点,x、y为该特征点坐标。
特征点匹配
同样可以看前面的参考资料,核心代码如下:
- //-- Step 2: Calculate descriptors (feature vectors)
- SurfDescriptorExtractor extractor;
- Mat descriptors_1, descriptors_2;
- extractor.compute(src1, keypoints_1, descriptors_1);
- extractor.compute(src2, keypoints_2, descriptors_2);
- //-- Step 3: Matching descriptor vectors with a brute force matcher
- FlannBasedMatcher matcher;
- std::vector< DMatch > matches;
- matcher.match(descriptors_1, descriptors_2, matches);
计算出来的匹配信息保存在matches中。注意:matches[i].queryIdx、matches[i].trainIdx:i表示当前为第几组匹配点,queryIdx表示该匹配点对应在keypoints_1上的存储位置,trainIdx表示该匹配点对应在keypoints_2上的存储位置。
特征点筛选
具体代码如下:
- //-- Step 4: Find good matcher
- 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;
- }
- for(i = 0; i < descriptors_1.rows; i++ ){
- if(matches[i].distance < 2*min_dist){
- count += 1;
- good_matches.push_back(matches[i]);
- good_keypoints_1.push_back(keypoints_1[matches[i].queryIdx]);
- good_keypoints_2.push_back(keypoints_2[matches[i].trainIdx]);
- }
- }
根据特征匹配之间的精度误差matches[i].distance,去掉精度误差较高的匹配点。然后将好的匹配点对应的保存到good_keypoints_1和good_keypoints_2中。
计算畸变仿射矩阵
主要是使用opencv函数:estimateRigidTransform来实现。核心代码如下:
- std::vector<Point2f> frame1_features_ok, frame2_features_ok;
- tmpPoint.x = good_keypoints_1[i].pt.x;
- tmpPoint.y = good_keypoints_1[i].pt.y;
- frame1_features_ok.push_back(tmpPoint);
- tmpPoint.x = good_keypoints_2[i].pt.x;
- tmpPoint.y = good_keypoints_2[i].pt.y;
- frame2_features_ok.push_back(tmpPoint);
- mat = estimateRigidTransform(frame1_features_ok, frame2_features_ok, true);
为了适配函数estimateRigidTransform输入参数,再分别将筛选出来比较好的匹配点存入到frame1_features_ok和frame2_features_ok中,函数返回的mat中,存储的就是畸变仿射矩阵。
输出结果
使用函数cvWarpAffine根据前面算出的仿射矩阵进行仿射变化。
- IplImage img = mat;
- cvConvert(&img, warp_mat);
- cvWarpAffine(&ipI1, &ipIdst, warp_mat);
结果显示[编辑 | 编辑源代码]
效果演示1: 原始图像1 原始图像2
图像1去配准图像2的结果
效果演示2: 原始图像1 原始图像2
图像1去配准图像2的结果
对应实例代码下载:http://download.csdn.net/detail/u011630458/9414194
0 0
- opencv实现最基本的图像配准
- opencv实现最基本的图像配准
- OpenCV(一) Mat数据结构--最基本的图像处理容器
- OpenCV-图像的基本操作
- opencv:图像的基本变换
- OpenCV最基本的测试代码-图像的读取与显示!
- OpenCv (正式篇)6----core组件--Mat(最基本的图像数据类型)
- opencv 实现图像的旋转
- 图像旋转的OpenCV实现
- opencv 实现图像的旋转
- OpenCV实现图像的旋转
- OpenCV实现图像的旋转
- opencv缩放图像的实现
- opencv实现图像的傅里叶变换
- opencv实现图像的缩放
- opencv的基本运用:打开,显示图像
- OpenCV学习笔记:基本的图像处理
- OpenCV随笔002-图像的基本操作
- 套接字选项
- findbug的使用原理和安装
- AXI DMA(2)简单的DMA传输寄存器编程顺序(不是SG)
- Android为什么不允许在子线程中访问UI?
- 关于百度地图导航退出unregisterReceiver异常
- opencv实现最基本的图像配准
- Java并发编程-同步辅助类之Exchanger
- 二叉树的中序遍历(非递归)
- java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderServlet服务器启动报异常
- 游戏服务登录流程
- http://mp.weixin.qq.com/s?__biz=MzAwODMyNjYxMQ==&mid=502716191&idx=1&sn=e916fa1a45fe91d162e1e71a2689
- 理解Window和WindowManager
- jQuery.Autocomplete实现自动完成参数详解
- Android设计模式-建造者模式