opencv实现最基本的图像配准

来源:互联网 发布:iphone写日记的软件 编辑:程序博客网 时间:2024/06/06 13:07
简介
  本篇是对基于opencv实现图像配准的实现笔记。

基本原理

  可以参考如下流程:          
  大致操作:             1、先拍摄两张有相同区域的图片,注意图片尺寸保持一致。             2、分别提取出图像的特征点(如果图像质量很差的话,可能需要先做些预处理操作)。             3、根据图像特征点,对它们做特征点匹配。             4、筛选出比较好的特征匹配点。             5、根据这些特征匹配点计算出畸变仿射矩阵。             6、使用算出来的矩阵进行图像匹配。

具体实现

特征点检测

  可以参考如下资料:使用FLANN进行特征点匹配  核心的大致代码为:
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. //-- Step 1: Detect the keypoints using SURF Detector  
  2. int minHessian = 800;  
  3. SurfFeatureDetector detector(minHessian );  
  4. std::vector<KeyPoint> keypoints_1, keypoints_2;  
  5. detector.detect(src1, keypoints_1);  
  6. detector.detect(src2, keypoints_2);  
  7. int i, count = 0;  
  src1和src2分别为配准测试图片,检测出来的图像特征点保存在:keypoints_1和keypoints_2中。注意结构:keypoints_1[i].pt.x和keypoints_1[i].pt.x :i表示当前为第几个特征点,x、y为该特征点坐标。

特征点匹配

  同样可以看前面的参考资料,核心代码如下:
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. //-- Step 2: Calculate descriptors (feature vectors)  
  2. SurfDescriptorExtractor extractor;  
  3. Mat descriptors_1, descriptors_2;  
  4. extractor.compute(src1, keypoints_1, descriptors_1);  
  5. extractor.compute(src2, keypoints_2, descriptors_2);  
  6.    
  7. //-- Step 3: Matching descriptor vectors with a brute force matcher  
  8. FlannBasedMatcher matcher;  
  9. std::vector< DMatch > matches;  
  10. matcher.match(descriptors_1, descriptors_2, matches);  
  计算出来的匹配信息保存在matches中。注意:matches[i].queryIdx、matches[i].trainIdx:i表示当前为第几组匹配点,queryIdx表示该匹配点对应在keypoints_1上的存储位置,trainIdx表示该匹配点对应在keypoints_2上的存储位置。

特征点筛选

  具体代码如下:
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. //-- Step 4: Find good matcher  
  2. double max_dist = 0; double min_dist = 100;  
  3. forint i = 0; i < descriptors_1.rows; i++ ){  
  4.     double dist = matches[i].distance;  
  5.     if(dist < min_dist )   
  6.         min_dist = dist;  
  7.     if(dist > max_dist )  
  8.         max_dist = dist;   
  9. }    
  10.    
  11. for(i = 0; i < descriptors_1.rows; i++ ){  
  12.     if(matches[i].distance < 2*min_dist){  
  13.         count += 1;  
  14.         good_matches.push_back(matches[i]);  
  15.         good_keypoints_1.push_back(keypoints_1[matches[i].queryIdx]);  
  16.         good_keypoints_2.push_back(keypoints_2[matches[i].trainIdx]);  
  17.     }  
  18. }   
  根据特征匹配之间的精度误差matches[i].distance,去掉精度误差较高的匹配点。然后将好的匹配点对应的保存到good_keypoints_1和good_keypoints_2中。

计算畸变仿射矩阵

  主要是使用opencv函数:estimateRigidTransform来实现。核心代码如下:
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. std::vector<Point2f> frame1_features_ok, frame2_features_ok;  
  2.    
  3. tmpPoint.x = good_keypoints_1[i].pt.x;        
  4. tmpPoint.y = good_keypoints_1[i].pt.y;        
  5. frame1_features_ok.push_back(tmpPoint);  
  6.    
  7. tmpPoint.x = good_keypoints_2[i].pt.x;        
  8. tmpPoint.y = good_keypoints_2[i].pt.y;        
  9. frame2_features_ok.push_back(tmpPoint);  
  10.    
  11. mat = estimateRigidTransform(frame1_features_ok, frame2_features_ok, true);  
  为了适配函数estimateRigidTransform输入参数,再分别将筛选出来比较好的匹配点存入到frame1_features_ok和frame2_features_ok中,函数返回的mat中,存储的就是畸变仿射矩阵。

输出结果

  使用函数cvWarpAffine根据前面算出的仿射矩阵进行仿射变化。
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. IplImage img = mat;  
  2. cvConvert(&img, warp_mat);  
  3. cvWarpAffine(&ipI1, &ipIdst, warp_mat);  

结果显示[编辑 | 编辑源代码]

 效果演示1:                                   原始图像1                                         原始图像2


                   图像1去配准图像2的结果


 效果演示2:                                                  原始图像1                                          原始图像2


                   图像1去配准图像2的结果
对应实例代码下载:http://download.csdn.net/detail/u011630458/9414194
0 0