最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

特徴点のマッチングを使用した映像安定化

この例では、不安定なプラットフォームから撮影されたビデオを安定化する方法を説明します。映像安定化の 1 つの方法は、イメージ内の際立った特徴を追跡し、これをアンカー ポイントとして、それに対するすべての摂動を取り除くことです。ただし、この手続きは、最初のビデオ フレームのどこに際立った特徴があるかについての知識を用いてブートストラップしなければなりません。この例では、そのような "事前" 知識がなくても有効な、映像安定化の方法について説明します。この方法は、代わりにビデオ シーケンス内の「背景面」を自動的に探索し、その観測された歪みを使ってカメラの動きを補正します。

この安定化アルゴリズムには 2 つの手順があります。まず、2 つのイメージ間における点の対応に関数 estimateGeometricTransform を適用して、ビデオ シーケンスにあるすべての隣接フレーム間のアフィン イメージ変換を決定します。次に、ビデオ フレームをワープさせてビデオを安定化します。アルゴリズムと表示の両方に Computer Vision System Toolbox™ を使用します。

この例は、映像安定化の例に似ています。主な違いは、「映像安定化の例」では追跡する領域が与えられているのに対し、この例ではそのような知識が与えられていない点です。両方の例で同じビデオが使用されます。

手順 1: ムービー ファイルからのフレームの読み取り

ここでは、ビデオ シーケンスの最初の 2 フレームを読み取ります。安定化アルゴリズムに色は必要なく、グレースケール イメージを使用すると速度が改善されるため、強度イメージとして読み取ります。以下に両方のフレームを並べて表示し、赤とシアンのカラー合成を作成して両者間のピクセル単位の差異を示します。2 つのフレーム間には、明らかに垂直および水平の大きなオフセットが見られます。

filename = 'shaky_car.avi';
hVideoSrc = vision.VideoFileReader(filename, 'ImageColorSpace', 'Intensity');

imgA = step(hVideoSrc); % Read first frame into imgA
imgB = step(hVideoSrc); % Read second frame into imgB

figure; imshowpair(imgA, imgB, 'montage');
title(['Frame A', repmat(' ',[1 70]), 'Frame B']);

figure; imshowpair(imgA,imgB,'ColorChannels','red-cyan');
title('Color composite (frame A = red, frame B = cyan)');

手順 2: 各フレームからの際立った点の収集

ここでの目標は、2 つのフレーム間の歪みを補正する変換を決定することです。これには、アフィン変換を返す関数 estimateGeometricTransform を使用できます。この関数への入力として、2 つのフレーム間における一連の点の対応関係を与えなければなりません。これらの対応関係を求めるには、まず両方のフレームから対象となる点を収集し、それらの間に想定できそうな対応関係を選択します。

この手順では、フレームごとにこうした候補点を作成します。もう片方のフレームにこれらの点に対応する点が存在する可能性をできるだけ高めるには、コーナーなどの際立ったイメージ特徴の周りの点が必要です。これには、最速のコーナー検出アルゴリズムの 1 つを実行する関数 detectFASTFeatures を使用します。

下の図には、両方のフレームから検出された点が表示されています。その中の多くが、木立ちの輪郭に沿った点、大きな交通標識のコーナー、自動車のコーナーなどの同じイメージ特徴をカバーしていることを確認してください。

ptThresh = 0.1;
pointsA = detectFASTFeatures(imgA, 'MinContrast', ptThresh);
pointsB = detectFASTFeatures(imgB, 'MinContrast', ptThresh);

% Display corners found in images A and B.
figure; imshow(imgA); hold on;
plot(pointsA);
title('Corners in A');

figure; imshow(imgB); hold on;
plot(pointsB);
title('Corners in B');

手順 3: 点の対応関係の選択

次に、上記で得た点の間の対応関係を選択します。各点について、それを中心とする FREAK (Fast Retina Keypoint) 記述子を抽出します。FREAK 記述子はバイナリであるため、点の間のマッチング コストにはハミング距離を使用します。フレーム A とフレーム B にある点が推定的にマッチされます。一意性の制約はないため、フレーム B からの点がフレーム A の複数の点に対応する場合もあります。

% Extract FREAK descriptors for the corners
[featuresA, pointsA] = extractFeatures(imgA, pointsA);
[featuresB, pointsB] = extractFeatures(imgB, pointsB);

現在のフレームと前のフレームで検出された特徴をマッチングします。FREAK 記述子はバイナリであるため、関数 matchFeatures はハミング距離を使って対応する点を探します。

indexPairs = matchFeatures(featuresA, featuresB);
pointsA = pointsA(indexPairs(:, 1), :);
pointsB = pointsB(indexPairs(:, 2), :);

下のイメージは、先に提示したものと同じカラー合成を示していますが、フレーム A からの点が赤で、フレーム B からの点が緑で追加されています。点の間に描かれた黄色いラインは、上記の手続きで選択された対応関係を示しています。これらの対応関係の多くは正しいものですが、かなりの数の外れ値もあります。

figure; showMatchedFeatures(imgA, imgB, pointsA, pointsB);
legend('A', 'B');

手順 4: ノイズの多い対応関係からの変換の推定

前の手順で得られた点の対応関係の多くは正しくありません。しかし、RANSAC アルゴリズムのバリエーションである M-estimator SAmple Consensus (MSAC) アルゴリズムを使用して、2 つのイメージ間における幾何学的変換のロバスト推定を導出することは可能です。MSAC アルゴリズムは、関数 estimateGeometricTransform に実装されています。この関数は、一連の点の対応関係が与えられると、有効なインライアの対応関係を探索します。それを基に、最初の点のセットからのインライアを 2 番目のセットからのインライアと最も緊密にマッチさせるようなアフィン変換を導出します。このアフィン変換は、次のような形式の 3 行 3 列の行列となります。

[a_1 a_3 0;
 a_2 a_4 0;
 t_x t_y 1]

パラメーター は変換のスケール、回転およびせん断効果を定義します。パラメーター は平行移動のパラメーターです。この変換を使用して、対応する特徴が同じイメージ位置に移るようイメージをワープさせることができます。

アフィン変換には、結像面だけしか変更できないという制限があります。したがって、走行中の自動車から撮影したこのビデオのような、3 次元のシーンから取った 2 つのフレーム間にある一般的な歪みを検出するタスクには適していません。ただし、この後で説明する特定条件の下であれば正しく機能します。

[tform, pointsBm, pointsAm] = estimateGeometricTransform(...
    pointsB, pointsA, 'affine');
imgBp = imwarp(imgB, tform, 'OutputView', imref2d(size(imgB)));
pointsBmp = transformPointsForward(tform, pointsBm.Location);

以下は、再投影されたフレーム B に重ね合わせたフレーム A を、再投影された点の対応関係と共に示すカラー合成です。結果は非常に良好で、インライアの対応関係がほぼ厳密に一致しています。イメージの中心部はともによく揃っており、赤とシアンのカラー合成がその領域ではほぼ純粋な白黒になっています。

インライアの対応関係はすべてイメージの背景にあり、前景にはないことに注意してください。前景自体は揃っていません。これは、背景の特徴が遠くにあり、無限遠の平面にあるかのように動作するためです。したがって、アフィン変換が結像面のみの変更に制限されていても、両方のイメージの背景面を揃えるにはそれで十分です。さらに、背景面がフレーム間で動かないか、大きく変化しないと仮定すれば、この変換は実際にはカメラの動きを捉えていることになります。したがって、この補正を行うとビデオが安定化することになります。この条件は、フレーム間のカメラの移動が十分に小さいか、あるいは逆に、ビデオのフレーム レートが十分に速いならば有効です。

figure;
showMatchedFeatures(imgA, imgBp, pointsAm, pointsBmp);
legend('A', 'B');

手順 5: 変換の近似と平滑化

一連のビデオ フレーム が与えられると、上記の手続きを使ってすべてのフレーム の間の歪みをアフィン変換 として推定することができます。したがって、最初のフレームに対するフレーム の累積歪みは、その前のすべてのフレーム間変換の積となります。すなわち、次のようになります。

上記アフィン変換の 6 つのパラメーターをすべて使用することもできますが、数値を簡素化し安定させるため、より簡潔な「スケール - 回転 - 平行移動」の変換として行列を再近似することにします。完全なアフィン変換には自由パラメーターが 6 つありますが、この変換の自由パラメーターは、倍率、角度および 2 つの平行移動の 4 つだけです。この新しい変換行列の形式は次のとおりです。

[s*cos(ang)  s*-sin(ang)  0;
 s*sin(ang)   s*cos(ang)  0;
        t_x         t_y   1]

この変換手続きを以下に示します。上で取得した変換 を、等価な「スケール - 回転 - 平行移動」 であてはめます。変換の置き換えによる誤差が最小限であることを示すため、両方の変換を用いてフレーム B を再投影し、この 2 つのイメージを赤とシアンのカラー合成として下に表示します。このイメージはモノクロで表示され、2 つの再投影間に見られるピクセル単位の相違はごくわずかであることが明らかです。

% Extract scale and rotation part sub-matrix.
H = tform.T;
R = H(1:2,1:2);
% Compute theta from mean of two possible arctangents
theta = mean([atan2(R(2),R(1)) atan2(-R(3),R(4))]);
% Compute scale from mean of two stable mean calculations
scale = mean(R([1 4])/cos(theta));
% Translation remains the same:
translation = H(3, 1:2);
% Reconstitute new s-R-t transform:
HsRt = [[scale*[cos(theta) -sin(theta); sin(theta) cos(theta)]; ...
  translation], [0 0 1]'];
tformsRT = affine2d(HsRt);

imgBold = imwarp(imgB, tform, 'OutputView', imref2d(size(imgB)));
imgBsRt = imwarp(imgB, tformsRT, 'OutputView', imref2d(size(imgB)));

figure(2), clf;
imshowpair(imgBold,imgBsRt,'ColorChannels','red-cyan'), axis image;
title('Color composite of affine and s-R-t transform outputs');

手順 6: ビデオ全体への適用

次に、上記の手順を適用してビデオ シーケンスを平滑化します。可読性を高めるため、2 つのイメージ間の変換を推定する上記の手続きは MATLAB® の関数 cvexEstStabilizationTform に含められています。関数 cvexTformToSRT も、一般的なアフィン変換を「スケール - 回転 - 平行移動」の変換に変えます。

各ステップで現在のフレーム間の変換 を計算します。これを s-R-t 変換 としてあてはめます。その後、これを最初のフレーム以降のカメラの動きをすべて記述する累積変換 と組み合わせます。ビデオ プレーヤーには、平滑化されたビデオの最後の 2 フレームが赤とシアンの合成として表示されます。

このコードでは、早期終了条件を削除して、ループでビデオ全体を処理させることもできます。

% Reset the video source to the beginning of the file.
reset(hVideoSrc);

hVPlayer = vision.VideoPlayer; % Create video viewer

% Process all frames in the video
movMean = step(hVideoSrc);
imgB = movMean;
imgBp = imgB;
correctedMean = imgBp;
ii = 2;
Hcumulative = eye(3);
while ~isDone(hVideoSrc) && ii < 10
    % Read in new frame
    imgA = imgB; % z^-1
    imgAp = imgBp; % z^-1
    imgB = step(hVideoSrc);
    movMean = movMean + imgB;

    % Estimate transform from frame A to frame B, and fit as an s-R-t
    H = cvexEstStabilizationTform(imgA,imgB);
    HsRt = cvexTformToSRT(H);
    Hcumulative = HsRt * Hcumulative;
    imgBp = imwarp(imgB,affine2d(Hcumulative),'OutputView',imref2d(size(imgB)));

    % Display as color composite with last corrected frame
    step(hVPlayer, imfuse(imgAp,imgBp,'ColorChannels','red-cyan'));
    correctedMean = correctedMean + imgBp;

    ii = ii+1;
end
correctedMean = correctedMean/(ii-2);
movMean = movMean/(ii-2);

% Here you call the release method on the objects to close any open files
% and release memory.
release(hVideoSrc);
release(hVPlayer);

計算中に、生のビデオ フレームおよび修正されたフレームの平均が算出されました。これらの平均値を並べて以下に表示します。左のイメージは生の入力フレームの平均を示しており、元のビデオに多量の歪みが含まれていたことが確認できます。一方、修正後のフレームの平均を示す右側では、イメージ中央部分の歪みがほとんどありません。前景の細部はぼやけていますが (自動車が前進しているため必然的な結果です)、安定化アルゴリズムの有効性はよく示されています。

figure; imshowpair(movMean, correctedMean, 'montage');
title(['Raw input mean', repmat(' ',[1 50]), 'Corrected sequence mean']);

参考文献

[1] Tordoff, B; Murray, DW. "Guided sampling and consensus for motion estimation." European Conference n Computer Vision, 2002.

[2] Lee, KY; Chuang, YY; Chen, BY; Ouhyoung, M. "Video Stabilization using Robust Feature Trajectories." National Taiwan University, 2009.

[3] Litvin, A; Konrad, J; Karl, WC. "Probabilistic video stabilization using Kalman filtering and mosaicking." IS&T/SPIE Symposium on Electronic Imaging, Image and Video Communications and Proc., 2003.

[4] Matsushita, Y; Ofek, E; Tang, X; Shum, HY. "Full-frame Video Stabilization." Microsoft® Research Asia.CVPR 2005.