【Matlab】基於特徵點的全景圖像拼接

http://cn.mathworks.com/examples/matlab-computer-vision/mw/vision_product-FeatureBasedPanoramicImageStitchingExample-feature-based-panoramic-image-stitching

概述

在機器視覺應用領域裏特徵檢測和匹配是一個很重要的算法,比如圖像配準、跟蹤和目標檢測。這個例子裏,我們用基於特徵的方法完成圖像拼接。處理的方法是先用圖像配準特徵點。不同於單圖像對配準,這裏是多圖像對的配準完成圖像拼接。

步驟一 加載圖片

% 以圖像集的方法加載圖片
buildingDir = fullfile(toolboxdir('vision'), 'visiondata', 'building');
buildingScene = imageSet(buildingDir);

% 顯示要拼接的所有圖片
montage(buildingScene.ImageLocation)

步驟二 圖像配準

使用下面的步驟來進行圖像對配準操作。

  1. 在I(n)和I(n-1)之間檢測和匹配特徵點
  2. 估算從I(n)映射到I(n-1)上的幾何變換T(n)
  3. 計算I(n)在全景圖裏的變換T(1)*…*T(n-1)*T(n).

    % 從圖片集中讀取第一幅圖像
    I = read(buildingScene, 1);

    % 將圖像轉爲灰度圖,再提取I(1)的特徵點,用的是surf算法。
    grayImage = rgb2gray(I);
    points = detectSURFFeatures(grayImage);
    [features, points] = extractFeatures(grayImage, points);

    % 初始化所有變換的恆等矩陣。
    tforms(buildingScene.Count) = projective2d(eye(3));

    % Iterate over remaining image pairs
    for n = 2:buildingScene.Count

    % Store points and features for I(n-1).
    % 存儲前一圖像的特徵點座標和值。
    pointsPrevious = points;
    featuresPrevious = features;

    % Read I(n).
    % 讀取第n張圖片。
    I = read(buildingScene, n);

    % Detect and extract SURF features for I(n).
    %檢測和提取surf特徵值。
    grayImage = rgb2gray(I);
    points = detectSURFFeatures(grayImage);
    [features, points] = extractFeatures(grayImage, points);

    % 匹配I(n)和I(n-1)之間對應的特徵點
    indexPairs = matchFeatures(features, featuresPrevious, ‘Unique’, true);

    matchedPoints = points(indexPairs(:,1), :);
    matchedPointsPrev = pointsPrevious(indexPairs(:,2), :);

    % 用MSAC算法計算幾何變化。
    tforms(n) = estimateGeometricTransform(matchedPoints, matchedPointsPrev,…
    ‘projective’, ‘Confidence’, 99.9, ‘MaxNumTrials’, 2000);

    % 計算T(1) * … * T(n-1) * T(n)
    tforms(n).T = tforms(n-1).T * tforms(n).T;
    end

這裏,所有tforms的變換都是相對於第一幅圖像的。主要是爲了方便圖像配準處理代碼,這樣就可以對所有圖像連續處理。但是,用第一張圖像做爲全景圖配準的起點,不能得到最佳的效果,原因是它會把全景圖所有的圖像都發生畸變。將變換式用中間的場景可以創建比較好的全景圖,畸變也最小。
先用projective2d outputLimits方法查找每個變換輸出的極限。輸出極限再用來自動查找中間場景圖像的輪廓。

imageSize = size(I);  % 所有的圖像尺寸都是一樣的

% 對每個投影變化找到輸出的空間座標限制值。
for i = 1:numel(tforms)
    [xlim(i,:), ylim(i,:)] = outputLimits(tforms(i), [1 imageSize(2)], [1 imageSize(1)]);
end

接着,計算每個變換X極限的平均值,找到中間的圖像。只用X方向上的極限是由於場景爲水平方向上的。如果有其他的圖像,X和Y方向上的極限都應當用來查找中心圖像。

avgXLim = mean(xlim, 2);

[~, idx] = sort(avgXLim);

centerIdx = floor((numel(tforms)+1)/2);

centerImageIdx = idx(centerIdx);

最後,將中心圖像的反變換應用到所有的圖像變換中。

Tinv = invert(tforms(centerImageIdx));

for i = 1:numel(tforms)
    tforms(i).T = Tinv.T * tforms(i).T;
end

步驟三 初始化全景圖

接下來,創建一個空的全景圖用來存放所有圖像。
outputLimits方法計算所有變換中最小和最大輸出限制。這個值用來計算全景圖的大小。

for i = 1:numel(tforms)
    [xlim(i,:), ylim(i,:)] = outputLimits(tforms(i), [1 imageSize(2)], [1 imageSize(1)]);
end

% 找到輸出空間限制的最大最小值
xMin = min([1; xlim(:)]);
xMax = max([imageSize(2); xlim(:)]);

yMin = min([1; ylim(:)]);
yMax = max([imageSize(1); ylim(:)]);

% 全景圖的寬高
width  = round(xMax - xMin);
height = round(yMax - yMin);

% 生成空數據的全景圖
panorama = zeros([height width 3], 'like', I);

步驟四 創建全景圖

imwarp將圖像映射到全景圖中,再用vision.AlphaBlender將圖像重疊起來。

blender = vision.AlphaBlender('Operation', 'Binary mask', ...
                              'MaskSource', 'Input port');

% Create a 2-D spatial reference object defining the size of the panorama.
xLimits = [xMin xMax];
yLimits = [yMin yMax];
panoramaView = imref2d([height width], xLimits, yLimits);

% Create the panorama.
for i = 1:buildingScene.Count

    I = read(buildingScene, i);

    % Transform I into the panorama.
    warpedImage = imwarp(I, tforms(i), 'OutputView', panoramaView);

    % Overlay the warpedImage onto the panorama.
    panorama = step(blender, panorama, warpedImage, warpedImage(:,:,1));
end

figure
imshow(panorama)

總結

這個例子展示瞭如何使用圖像配準方法創建全景圖。附錄包含了圖像融合和對齊的全景圖拼接改進方法。

相關論文

[1] Matthew Brown and David G. Lowe. 2007. Automatic Panoramic Image Stitching using Invariant Features. Int. J. Comput. Vision 74, 1 (August 2007), 59-73.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章