Стабилизация видео с использованием соответствия функции точки

Этот пример показывает, как стабилизировать видео, которое было захвачено с джиттерной платформы. Один из способов стабилизировать видео - отследить характерную функцию изображения и использовать это в качестве опорной точки, чтобы отменить все возмущения относительно него. Эта процедура, однако, должна быть загружена со знанием того, где такая характерная функция лежит в первом видеокадре. В этом примере мы исследуем метод стабилизации видео, который работает без каких-либо априорных знаний. Вместо этого он автоматически ищет «фоновую плоскость» в видеопоследовательности и использует наблюдаемое искажение для коррекции движения камеры.

Этот алгоритм стабилизации включает два шага. Во-первых, мы определяем аффинные преобразования изображений между всеми соседними системами координат видеопоследовательности, используя estimateGeometricTransform2D функция, примененная к соответствиям двум изображениям. Во-вторых, мы деформируем видеокадры, чтобы получить стабилизированное видео. Мы будем использовать Computer Vision Toolbox™, как для алгоритма, так и для отображения.

Шаг 1. Чтение систем координат из файла фильма

Здесь мы читаем в первых двух системах координат видеопоследовательности. Мы читаем их как изображения интенсивности, так как цвет не нужен для алгоритма стабилизации, и потому что использование полутоновых изображений улучшает скорость. Ниже мы покажем обе системы координат один за другим, и мы производим красно-голубой цветовой композит, чтобы проиллюстрировать пиксельное различие между ними. Очевидно, что между двумя системами координат имеется большое вертикальное и горизонтальное смещение.

filename = 'shaky_car.avi';
hVideoSrc = VideoReader(filename);

imgA = rgb2gray(im2single(readFrame(hVideoSrc))); % Read first frame into imgA
imgB = rgb2gray(im2single(readFrame(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. Сбор характерных точек из каждой системы координат

Наша цель - определить преобразование, которое исправит искажение между двумя системами координат. Мы можем использовать estimateGeometricTransform2D функция для этого, которая вернёт смежное преобразование. В качестве входных данных мы должны предоставить этой функции набор точки соответствий между двумя системами координат. Чтобы сгенерировать эти соответствия, мы сначала собираем точки интереса из обеих систем координат, затем выбираем вероятные соответствия между ними.

На этом шаге мы генерируем эти потенциальные точки для каждой системы координат. Чтобы иметь лучший шанс, что эти точки будут иметь соответствующие точки в другой системе координат, мы хотим точки вокруг характерных функций изображения, таких как углы. Для этого мы используем 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. Выберите соответствия между точками

Далее мы выбираем соответствия между точками, выведенными выше. Для каждой точки мы извлекаем дескриптор Fast Retina Keypoint (FREAK) с центром вокруг него. Стоимостью соответствия, которую мы используем между точками, является Расстояние Хемминга, поскольку дескрипторы 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. Оценка преобразования из шумных соответствий

Многие из точки соответствий, полученных на предыдущем шаге, неправильны. Но мы все еще можем вывести надежную оценку геометрического преобразования между двумя изображениями с помощью алгоритма M-estimator SAmple Consensus (MSAC), который является вариантом алгоритма RANSAC. Алгоритм MSAC реализован в estimateGeometricTransform2D функция. Эта функция, когда задан набор соответствий точек, будет искать допустимые соответствия inlier. Из них он затем выведет смежное преобразование, которое заставляет inliers из первого набора точек наиболее тесно совпадать с inliers из второго набора. Это смежное преобразование будет матрицей 3х3 вида:

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

Параметры a задайте масштабные, вращательные и сдвигающие эффекты преобразования, в то время как параметры t являются параметрами перевода. Это преобразование может использоваться, чтобы деформировать изображения таким образом, чтобы их соответствующие функции были перемещены в то же место изображения.

Ограничение смежного преобразования заключается в том, что это может только изменить плоскость формирования изображения. Таким образом, он плохо подходит для нахождения общего искажения между двумя системами координат, взятыми из 3-D сцены, например, с помощью этого видео, взятого из движущейся машины. Но он работает при определенные обстоятельства, которые мы опишем в ближайшее время.

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

Ниже представлен композитный цвет, показывающий кадр A, наложенный на перепроектированный кадр B, наряду с перепроектированными соответствиями точек. Результаты превосходны, с inlier соответствиями почти в точности совпадают. Ядра изображений оба хорошо выровнены, так что красно-голубой цветной композит становится почти чисто черно-белым в этой области.

Обратите внимание, как все соответствия inlier находятся в фоновом режиме изображения, а не в переднем плане, который сам по себе не выровнен. Это происходит потому, что функции достаточно отдалены, что они ведут себя так, как будто они находятся на бесконечно удаленной плоскости. Таким образом, даже несмотря на то, что смежное преобразование ограничено изменением только плоскости формирования изображения, здесь этого достаточно для выравнивания фоновых плоскостей обоих изображений. Кроме того, если мы предполагаем, что фоновая плоскость не перемещалась или значительно изменялась между системами координат, то это преобразование на самом деле захватывает движение камеры. Поэтому исправление для этого стабилизирует видео. Это условие будет держаться, пока движение камеры между системами координат достаточно мало, или, наоборот, если частота видеокадров достаточно высока.

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

Шаг 5. Преобразование приближения и сглаживания

Учитывая набор видеокадров Ti,i=0,1,2теперь мы можем использовать вышеописанную процедуру, чтобы оценить искажение между всеми системами координат Ti и Ti+1 как смежные преобразования, Hi. Таким образом, совокупное искажение системы координат i относительно первой системы координат будет продуктом всех предыдущих межкадровых преобразований, или

Hcumulative,i=Hij=0i-1

Мы могли бы использовать все шесть параметров смежного преобразования выше, но, для численной простоты и устойчивости, мы принимаем решение переподгонять матрицу как более простое преобразование масштаб-поворот-перевод. Это имеет только четыре свободных параметра по сравнению с шестью полным смежным преобразованием: один масштабный коэффициент, один угол и два перевода. Эта новая матрица преобразования имеет вид:

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

Мы покажем эту процедуру преобразования ниже, подгоняя полученное выше преобразование H с эквивалентным переводом вращения шкалы, HsRt. Чтобы показать, что ошибка преобразования преобразования минимальна, мы перепроектируем кадр B с обоими преобразованиями и покажем два изображения ниже в виде красно-голубого цветного композита. Поскольку изображение выглядит черно-белым, очевидно, что пиксельное различие между различными репроекциями незначительно.

% 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. Прокрутка Полного Видео

Теперь мы применяем вышеописанные шаги для сглаживания видеоряда. Для читаемости вышеуказанная процедура оценки преобразования между двумя изображениями была помещена в функцию MATLAB ® cvexEstStabilizationTform. Функция cvexTformToSRT также преобразует общее смежное преобразование в преобразование масштаб-поворот-перевод.

На каждом шаге вычисляем преобразование H между настоящими системами координат. Мы подбираем это как преобразование s-R-t, HsRt. Затем мы комбинируем это совокупное преобразование, Hcumulative, который описывает все движения камеры с момента первой системы координат. Последние две системы координат сглаженного видео показаны в Video Player в виде красно-голубого композита.

С помощью этого кода вы также можете вывести условие раннего выхода, чтобы цикл обработал все видео.

% Reset the video source to the beginning of the file.
read(hVideoSrc, 1);
                      
hVPlayer = vision.VideoPlayer; % Create video viewer

% Process all frames in the video
movMean = rgb2gray(im2single(readFrame(hVideoSrc)));
imgB = movMean;
imgBp = imgB;
correctedMean = imgBp;
ii = 2;
Hcumulative = eye(3);
while hasFrame(hVideoSrc) && ii < 10
    % Read in new frame
    imgA = imgB; % z^-1
    imgAp = imgBp; % z^-1
    imgB = rgb2gray(im2single(readFrame(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(hVPlayer);

Во время расчета мы вычисляли среднее значение необработанных видеокадров и исправленных кадров. Эти средние значения показаны один за другим ниже. Левое изображение показывает среднее значение необработанных входных кадров, доказывая, что в исходном видео было много искажений. Среднее значение исправленных кадров справа, однако, показывает ядро изображения почти без искажений. Хотя детали переднего плана были размыты (как необходимый результат движения автомобиля вперед), это показывает эффективность алгоритма стабилизации.

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

Ссылки

[1] Tordoff, B; Мюррей, DW. «Ориентированная выборка и консенсус для оценки движения». Европейская конференция n Компьютерное Зрение, 2002.

[2] Lee, KY; Chuang, YY; Chen, BY; Ouhyoung, M. «Video Stabilization with Robust Feature Trajectories». Национальный Тайваньский университет, 2009.

[3] Литвин, А; Конрад, Дж; Карл, туалет. Вероятностная стабилизация видео с помощью фильтрации Калмана и мозаики. IS & T/SPIE Symposium on Electronic Imaging, Image and Video Communications and Proc., 2003.

[4] Matsushita, Y; Ofek, E; Tang, X; Шум, HY. «Полнокадровая стабилизация видео». Microsoft ® Research Asia. CVPR 2005.