opencv实现最基本的图像配准

简介

  本篇是对基于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
  • 9
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
图像配准是计算机视觉中非常重要的一个问题,多项式配准是其中的一种方法。OpenCV提供了一些函数来实现多项式图像配准,下面是一个简单的例子。 首先,我们需要导入必要的库和读取两幅图像: ```python import cv2 import numpy as np img1 = cv2.imread('img1.jpg', 0) img2 = cv2.imread('img2.jpg', 0) ``` 接下来,我们使用`cv2.findHomography()`函数来计算变换矩阵,该函数可以通过最小二乘法计算出两幅图像之间的透视变换矩阵。我们可以通过以下方式调用该函数: ```python M, mask = cv2.findHomography(pts_src, pts_dst, cv2.RANSAC, 5.0) ``` 其中`pts_src`和`pts_dst`是源图像和目标图像中对应的特征点坐标,`cv2.RANSAC`是估计变换矩阵时使用的方法,`5.0`是RANSAC算法的阈值。 然后,我们可以使用`cv2.warpPerspective()`函数将源图像进行透视变换,从而与目标图像对齐: ```python height, width = img1.shape im_out = cv2.warpPerspective(img1, M, (width, height)) ``` 最后,我们可以将两幅图像进行拼接: ```python result = cv2.addWeighted(img2, 0.5, im_out, 0.5, 0) ``` 完整的代码如下: ```python import cv2 import numpy as np img1 = cv2.imread('img1.jpg', 0) img2 = cv2.imread('img2.jpg', 0) # 寻找特征点 orb = cv2.ORB_create() keypoints1, descriptors1 = orb.detectAndCompute(img1, None) keypoints2, descriptors2 = orb.detectAndCompute(img2, None) # 特征点匹配 bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) matches = bf.match(descriptors1, descriptors2) matches = sorted(matches, key=lambda x:x.distance) # 取前10个最佳匹配 pts_src = np.float32([keypoints1[m.queryIdx].pt for m in matches[:10]]).reshape(-1, 1, 2) pts_dst = np.float32([keypoints2[m.trainIdx].pt for m in matches[:10]]).reshape(-1, 1, 2) # 计算变换矩阵 M, mask = cv2.findHomography(pts_src, pts_dst, cv2.RANSAC, 5.0) # 透视变换 height, width = img1.shape im_out = cv2.warpPerspective(img1, M, (width, height)) # 图像拼接 result = cv2.addWeighted(img2, 0.5, im_out, 0.5, 0) cv2.imshow('Result', result) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在这个例子中,我们使用`ORB`算法寻找两幅图像中的特征点,并使用`BFMatcher`算法进行特征点匹配。然后,我们使用`findHomography`函数计算变换矩阵,最后使用`warpPerspective`函数进行透视变换。最终,我们将两幅图像进行拼接,得到了对齐后的图像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值