1. 程式人生 > >maltab-影象拼接(左右兩幅圖)

maltab-影象拼接(左右兩幅圖)

 

影象拼接

參考自 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軸範圍都採用了權重再分配,而不是那個精確的重疊區域不規則圖形。

[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('漸入漸出融合');

  

 

 看出,效果還是不錯的,沒有一點點邊緣的痕跡。但是最下方有書本的陰影出現,我猜想是我對重疊區域的處理不夠準確引起的。大家可以試試準確的處理這個不規則重疊區域的權重再分配。

歡迎大家向博主分享,一同學習。