基于MATLAB的Harris角点检测完成图片全景拼接

目录

  1. 作业概要 1
  2. 原理及实现 1
    2.1. 模块1 Harris角点检测 1
  3. 根据角点响应函数计算每个像素点的角点响应值; 2
    2.2. 模块2 关键点的描述及其匹配 3
    2.2.1. 生成描述向量 3
    2.2.2. 匹配描述子 4
  4. 输出matched_points和匹配点对数count; 5
    2.3. 模块3 转换矩阵的估计 5
  5. 输出仿射变换矩阵H。 6
    2.4. 模块4 RANSAC 7
  6. 取前num_inliers个随机点对拟合仿射变换矩阵H; 8
    2.5. 模块5 梯度方向直方图 10
  7. 根据梯度方向分类(代码里写了一个分类器sorter); 11
    2.6. 模块6 更佳的图片融合策略(线性融合) 12
  8. 确定融合区域的左边界和右边界; 12
    2.7. 模块7 函数封装 14
    2.8. 模块8 Matlab自带的SURF实现 14
    2.9. 模块9 基于Matlab自带的SURF写的“全景拼接” 15
    2.10. 其他图片的匹配 16
  9. 总结 16

原理简介:
直接求解仿射变换矩阵的结果并不是很理想,这是因为在确定对应点时,我们的限制条件并不算精确,导致引入了许多无效数据。我们可以利用RANSAC方法来进一步对数据进行筛选,求解变换矩阵。
RANSAC是“RANdom SAmple Consensus(随机抽样一致)”的缩写。它可以从一组包含“外点”的观测数据集中,通过迭代方式估计数学模型的参数。它是一种不确定的算法——它有一定的概率得出一个合理的结果;为了提高概率必须提高迭代次数。
这里滤除误匹配对采用RANSAC算法寻找一个最佳变换矩阵H,矩阵大小为3×3。RANSAC目的是找到最优的参数矩阵使得满足该矩阵的数据点个数最多。由于仿射变换矩阵有6个未知参数,至少需要6个线性方程求解,对应到点位置信息上,一组点对可以列出两个方程,则至少包含3组匹配点对。同理透视变换就需要找4对点。作业中的RANSAC的主要步骤包括了:
1.随机选取对应点;
2.计算变换矩阵;
3.在给定的阈值范围内计算有效数据点数(inliers);
4.重复步骤1-3,记录下最多的有效点数;
5.利用有效的数据点和最小二乘法重新计算变换矩阵。

函数实现:
ransac.m

输入:
keypoints1:(m2)img1角点坐标索引矩阵。
keypoints2:(n
2)img2角点坐标索引矩阵。
matched_points:(p*2)矩阵,保存匹配上的角点的坐标。
iterations:RANSAC迭代次数。
thres:RANSAC误差阈值。
num_inliers:取num_inliers对点估计模型。

输出:
ransac_matched_points:(q*2)矩阵,保存RANSAC方法剔除误匹配后的匹配点坐标。
count_inliers:RANSAC方法剔除误匹配后的匹配点个数。

步骤:
1.随机打乱匹配点顺序,计算打乱后的匹配点坐标sub_matched1和sub_matched2;
2.取前num_inliers个随机点对拟合仿射变换矩阵H;
3.根据拟合出来的变换矩阵计算img1中的角点的变换结果sub_transed;
4.计算误差,这里误差的描述取sub_transed和sub_matched2的比值-1的绝对值;
5.计算sub_transed中小于误差的点的个数;
6.重复步骤1-4至设置好的迭代次数,记录下最多的内点数;
7.输出最多内点时的内点集合以及内点个数;
8.根据输出的内点集合重新拟合仿射变换矩阵。

误差描述好像还有其他方法,例如计算前后两个矩阵的范数等,可以采取一些扩大误差的方法得到更精确的内点集合。RANSAC迭代一定次数后计算结果不会变的更好。RANSAC方法迭代500次,误差阈值取0.003,比例阈值k取0.8时,一般会剔除220对左右的匹配点,效果如下:

function [t_img1,t_img2]=img_trans(img1,img2,affine_matrix)

T=affine_matrix;
Tr=[T(1,1),T(1,2),0;T(2,1),T(2,2),0;0 0 1];
Tx=T(1,3);
Ty=T(2,3);

Tr=affine2d(Tr);
followOutput = affineOutputView(size(img2),Tr,'BoundsStyle','FollowOutput');
t_img1=img1;
t_img2=imwarp(img2,Tr,'OutputView',followOutput);

if Tx>0
    methodx='post';
else
    methodx='pre';
end

if Ty>0
    methody='post';
else
    methody='pre';
end

t_img2=padarray(t_img2,abs(floor(Tx)),0,methodx);
t_img2=padarray(rot90(t_img2),abs(floor(Ty)),0,methody);
t_img2=rot90(t_img2);
t_img2=rot90(t_img2);
t_img2=rot90(t_img2);

t_img1=padarray(t_img1,abs(size(t_img2,1)-size(t_img1,1)),0,'post');
t_img1=padarray(rot90(t_img1),abs(size(t_img2,2)-size(t_img1,2)),0,'pre');
t_img1=rot90(t_img1);
t_img1=rot90(t_img1);
t_img1=rot90(t_img1);

end

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/newlw/article/details/129416201
今日推荐