图像拼接
参考自 https://blog.csdn.net/m0_37565736/article/details/79865990 并修改了其中错误的地方,添加自己的讲解或者看法。
我要拼接的是一副画卷,如下(大小一样的,都是3000*4000像素)
首先,就是读取图像
clear all
clc
file1='G:/picture/a.jpg';
file2='G:/picture/b.jpg';
I1=imread(file1);%读取图片
I2=imread(file2); imgs=[I1,I2];
figure,imshow(imgs);%并排显示两幅待拼接图像
title('待拼接图像');
但是,读出来的图像在imshow中被旋转了一下,出来是这个样子的
这样就这样吧。。不影响操作
下一步将其灰度化,并提取SURF特征点。
img1=rgb2gray(I1);
img2=rgb2gray(I2);
imageSize=size(img1); p1=detectSURFFeatures(img1);
p2=detectSURFFeatures(img2);%检测SURF特征点
然后提取特征向量并加以匹配
[img1Features, p1] = extractFeatures(img1, p1);%使用64维向量表示特征描述子,
%第一个返回的参数即为每个特征点对应的特征描述子,第二个参数是特征点
[img2Features, p2] = extractFeatures(img2, p2);
boxPairs = matchFeatures(img1Features, img2Features);%特征描述子匹配 matchedimg1Points = p1(boxPairs(:, 1));%第二个参数:可以不加,因为其为n行1列的结构体数组
matchedimg2Points = p2(boxPairs(:, 2));
这时我们可以看到,匹配成功的特征点密密麻麻的,甚至篮圈里面的特征点匹配还有问题,怎么可能匹配上嘛。
所以,我们接下来要去除误匹配点,进行MSAC算法实现。另外,通过特征点匹配还得到了第二幅图的变换矩阵tform,第二幅图要经过变换矩阵变成和第一幅图的坐标一致
[tform, inlierimg2Points, inlierimg1Points] = ...
estimateGeometricTransform(matchedimg2Points, matchedimg1Points, 'projective');%射影变换,tfrom映射点对1内点到点对2内点
%该函数使用随机样本一致性(RANSAC)算法的变体MSAC算法实现,去除误匹配点
%The returned geometric transformation matrix maps the inliers in matchedPoints1
%to the inliers in matchedPoints2.返回的几何映射矩阵映射第一参数内点到第二参数内点 showMatchedFeatures(I1, I2, inlierimg1Points, ...
inlierimg2Points, 'montage');
title('Matched Points (Inliers Only)');
好,精确匹配之后,看到匹配的总体就好多了,看上去很准确。把两幅图共有的部分都匹配上了。
下一步进行图像合并,tform是变换矩阵,以第一幅图像为基准坐标,第二幅图要进行变换与其对应,
Rfixed就是第一幅图的世界二维坐标。
Rfixed = imref2d(size(I1));
[registered2, Rregistered] = imwarp(I2, tform);
%[registered1, Rregistered1] = imwarp(I1, tform);
figure()
imshowpair(I1,Rfixed,registered2,Rregistered,'blend');
title('图像差异');
按照特征点直接来拼接,是这个样子滴,看到第二幅图经过变换矩阵后稍微倾斜了一下,然后特征点匹配后会出现两条明显的边缘,在y=0和y=1500的地方。
下面的操作就是要消除这两个边缘。让其完美的融入。
我用的是参考博客上的渐入渐出的原理。大家有好的方法欢迎给博主分享。
渐入渐出融合
所谓渐入渐出就是将两幅图重合的区域按照距离两幅图的距离按照一定的权重重新分配重合部分图画的三原色权重。比如最中间的就是0.5 0.5的比例。
那么,下一步就是找到他们重叠区域了,也就是相同掩模区。
先确定一下整体的像素大小以及两幅图的实际具体位置。
[xlim, ylim] = outputLimits(tform, [1 imageSize(2)], [1 imageSize(1)]);%输出坐标范围 x:23.8~4334 y:-1844~1447
% 找到输出空间限制的最大最小值
xMin = min([1; xlim(:)]);%1
xMax = max([imageSize(2); xlim(:)]);%4334 yMin = min([1; ylim(:)]);%-1844
yMax = max([imageSize(1); ylim(:)]);%3000 % 全景图的宽高
width = round(xMax - xMin);
height = round(yMax - yMin); %创建2D空间参考对象定义全景图尺寸
xLimits = [xMin xMax];
yLimits = [yMin yMax];
panoramaView = imref2d([height width ], xLimits, yLimits); % 变换图片到全景图.
unwarpedImage = imwarp(I1,projective2d(eye(3)), 'OutputView', panoramaView);
warpedImage = imwarp(I2, tform, 'OutputView', panoramaView);
以第一幅图为基准找到重叠区域(掩模区)
第三张图就是两幅图的共同区域了。我们在这个区域里面对两幅图像色彩的权重进行重新的分配,然后显示图像。
这幅图就是 第一张图的权重分配,理他近的边缘权重为1,离他最远的重合位置边缘权重为0.为了避免使用for循环增加计算时间,我只能将整个x轴范围都采用了权重再分配,而不是那个精确的重叠区域不规则图形。
% % %%%%%%%%%%%%%%%%%%%%%%%%%%渐入渐出融合%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MAKE MASKS FOR BOTH IMAGES
% warpedImage(isnan(warpedImage))=0; % newImage = zeros(size(warpedImage));
% newImage(1:size(I1,1), 1: size(I1,2)+100,:) = I1;
newImage=unwarpedImage;
newImage=double(newImage); balck1=(warpedImage(:,:,1)==0 & warpedImage(:,:,2)==0 & warpedImage(:,:,3)==0);
balck2=(newImage(:,:,1)==0 & newImage(:,:,2)==0 & newImage(:,:,3)==0);
black=and(balck1,balck2);
black=~black; maskA = (warpedImage(:,:,1)>0 |warpedImage(:,:,2)>0 | warpedImage(:,:,3)>0);%变换图像掩膜
mask1 = (newImage(:,:,1)>0 | newImage(:,:,2)>0 | newImage(:,:,3)>0);%非变换图像掩膜
mask1 = and(maskA, mask1);%重叠区掩膜
% figure,imshow(mask1)
[row,col] = find(mask1==1);
left = min(col);
right = max(col);%获得重叠区左右范围
up=min(row);
down=max(row);
mask = ones(size(mask1));
% figure()
% imshow(mask)
%mask(:,left:right) = repmat(linspace(0,1,right-left+1),size(mask,1),1);%复制平铺矩阵
mask(up:down,:) = repmat(linspace(1,0,down-up+1)',1,size(mask,2));%复制平铺矩阵
% BLEND EACH CHANNEL
warpedImage=double(warpedImage);
% figure()
% warpedImage=uint8(warpedImage);
% imshow(warpedImage)
% figure()
% imshow(mask)
warpedImage(:,:,1) = warpedImage(:,:,1).*mask;
warpedImage(:,:,2) = warpedImage(:,:,2).*mask;
warpedImage(:,:,3) = warpedImage(:,:,3).*mask; % REVERSE THE ALPHA VALUE
%mask(:,left:right) = repmat(linspace(1,0,right-left+1),size(mask,1),1);
mask(up:down,:) = repmat(linspace(0,1,down-up+1)',1,size(mask,2));%复制平铺矩阵
newImage(:,:,1) = newImage(:,:,1).*mask;
newImage(:,:,2) = newImage(:,:,2).*mask;
newImage(:,:,3) = newImage(:,:,3).*mask; newImage(:,:,1) = warpedImage(:,:,1) + newImage(:,:,1);
newImage(:,:,2) = warpedImage(:,:,2) + newImage(:,:,2);
newImage(:,:,3) = warpedImage(:,:,3) + newImage(:,:,3); % newImage(:,:,1) = newImage(:,:,1).*black;
% newImage(:,:,2) = newImage(:,:,2).*black;
% newImage(:,:,3) = newImage(:,:,3).*black;
newImage=uint8(newImage);
figure()
imshow(newImage);
title('渐入渐出融合');
看出,效果还是不错的,没有一点点边缘的痕迹。但是最下方有书本的阴影出现,我猜想是我对重叠区域的处理不够准确引起的。大家可以试试准确的处理这个不规则重叠区域的权重再分配。
欢迎大家向博主分享,一同学习。