パノラマの作成
この例では、複数のイメージを自動的に繋ぎ合わせてパノラマを作成する方法を示します。イメージを繋ぎ合わせる手続きは、特徴ベースのイメージ レジストレーションを拡張したものです。1 組のイメージ ペアのレジストレーションを行う代わりに、複数のイメージ ペアを互いに比較しながらレジストレーションを連続的に行い、パノラマを形成します。
イメージの読み込み
この例で使用するイメージ セットには建物の写真が含まれています。これらの写真は、キャリブレーションされていないスマート フォン カメラを左から右へ水平に移動させて、建物のすべての部分をカバーするように撮影したものです。イメージにはレンズ歪みの影響が比較的少ないため、カメラのキャリブレーションは必要ありません。しかし、レンズ歪みがある場合は、パノラマを作成する前にカメラのキャリブレーションを行い、イメージの歪みを補正しなければなりません。必要に応じてカメラ キャリブレーターアプリを使用し、カメラのキャリブレーションを行います。
イメージを読み込んで表示します。
buildingDir = fullfile(toolboxdir("vision"),"visiondata","building"); buildingScene = imageDatastore(buildingDir); montage(buildingScene.Files)

イメージ ペアのレジストレーション
パノラマを作成するには、まず次の手順によって、連続したイメージ ペアのレジストレーションを行います。
と の間で特徴を検出し、マッチングします。
を にマッピングする幾何学的変換 を推定します。
をパノラマ イメージに としてマッピングする変換を計算します。
イメージ セットから最初のイメージを読み取ります。
I = readimage(buildingScene,1);
最初のイメージで特徴を初期化します。
grayImage = im2gray(I); points = detectSURFFeatures(grayImage); [features,points] = extractFeatures(grayImage,points);
すべての変換を単位行列に初期化します。建物のイメージがカメラにかなり近いため、射影変換を使用していることに注意してください。より遠くから撮影されたシーンの場合は、アフィン変換の使用を検討してください。
numImages = numel(buildingScene.Files); tforms(numImages) = projtform2d;
イメージ サイズを保持する変数を初期化します。
imageSize = zeros(numImages,2);
残りのイメージ ペアについても同じ処理を繰り返します。各イメージについて、前のイメージのポイントと特徴を保存します。その後、それを読み取ってグレースケールに変換し、イメージ サイズを保存します。イメージから SURF 特徴量を検出して抽出し、前のイメージとの対応関係を見つけます。次に、2 つの対応間の変換を推定します。
for n = 2:numImages pointsPrevious = points; featuresPrevious = features; I = readimage(buildingScene, n); grayImage = im2gray(I); imageSize(n,:) = size(grayImage); points = detectSURFFeatures(grayImage); [features,points] = extractFeatures(grayImage,points); indexPairs = matchFeatures(features,featuresPrevious,Unique=true); matchedPoints = points(indexPairs(:,1), :); matchedPointsPrev = pointsPrevious(indexPairs(:,2), :); tforms(n) = estgeotform2d(matchedPoints, matchedPointsPrev,... "projective",Confidence=99.9,MaxNumTrials=2000); tforms(n).A = tforms(n-1).A * tforms(n).A; end
この段階では、tforms 内のすべての変換は最初のイメージに対する相対的な変換になっています。これによりイメージの遂次処理が可能になり、イメージのレジストレーション手順のコーディングが簡単になります。ただし、最初のイメージからパノラマを開始すると、パノラマを構成するイメージのほとんどが歪む傾向があるため、見た目があまり美しくない結果になることがよくあります。シーンの中央で歪みが一番少なくなるように変換を調整することで、より見栄えの良いパノラマを作成することができます。この改善を行うには、中央のイメージの変換を反転させて、この逆変換をそれ以外のすべてのイメージに適用します。まずprojtform2d outputLimits メソッドを使用して各変換の出力範囲を求めます。その後、この出力範囲を使ってシーンのほぼ中央にあるイメージを自動的に見つけます。
各変換の出力範囲を計算します。
for idx = 1:numel(tforms) [xlim(idx,:),ylim(idx,:)] = outputLimits(tforms(idx),[1 imageSize(idx,2)],[1 imageSize(idx,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 idx = 1:numel(tforms) tforms(idx).A = Tinv.A * tforms(idx).A; end
パノラマの初期化
すべてのイメージをマッピングする対象となる、初期の空白のパノラマを作成します。outputLimits メソッドを使用して、すべての変換にわたる出力範囲の最小値と最大値を計算します。これらの値は、パノラマのサイズを自動計算するために使用されます。
for idx = 1:numel(tforms) [xlim(idx,:),ylim(idx,:)] = outputLimits(tforms(idx),[1 imageSize(idx,2)],[1 imageSize(idx,1)]); end maxImageSize = max(imageSize);
出力範囲の最小値と最大値を見つけます。
xMin = min([1; xlim(:)]); xMax = max([maxImageSize(2); xlim(:)]); yMin = min([1; ylim(:)]); yMax = max([maxImageSize(1); ylim(:)]);
パノラマの幅と高さを計算します。
width = round(xMax - xMin); height = round(yMax - yMin);
イメージ I のタイプと特性に合わせて、次元が [height width 3] であるゼロの配列を設定し、パノラマを空白のキャンバスで初期化します。
panorama = zeros([height width 3],"like",I);パノラマの作成
imwarpを使用してイメージをパノラマにマッピングし、imblendを使用してイメージを重ね合わせます。
パノラマのサイズを定義する 2 次元空間参照オブジェクトを作成します。
xLimits = [xMin xMax]; yLimits = [yMin yMax]; panoramaView = imref2d([height width],xLimits,yLimits);
各イメージをワーピングさせてパノラマに変換し、パノラマを作成します。次に、バイナリ マスクを生成し、ワーピングさせたイメージをパノラマに重ねます。
for idx = 1:numImages I = readimage(buildingScene,idx); warpedImage = imwarp(I,tforms(idx),OutputView=panoramaView); mask = imwarp(true(size(I,1),size(I,2)),tforms(idx),OutputView=panoramaView); panorama = imblend(warpedImage,panorama,mask,foregroundopacity=1); end 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.