В этом примере показано, как стабилизировать видео, снятое с джиттерной платформы. Одним из способов стабилизации видео является отслеживание характерного признака изображения и использование его в качестве точки привязки для устранения всех возмущений относительно него. Эта процедура, однако, должна быть загружена со знанием того, где такая характерная особенность лежит в первом видеокадре. В этом примере мы исследуем метод стабилизации видео, который работает без каких-либо таких априорных знаний. Вместо этого он автоматически выполняет поиск «фоновой плоскости» в видеопоследовательности и использует наблюдаемое искажение для коррекции движения камеры.
Этот алгоритм стабилизации включает в себя два шага. Сначала мы определяем аффинные преобразования изображения между всеми соседними кадрами видеопоследовательности, используя estimateGeometricTransform2D функция, применяемая к точкам соответствия между двумя изображениями. Во-вторых, мы искажаем видеокадры, чтобы получить стабилизированное видео. Мы будем использовать Toolbox™ компьютерного зрения, как для алгоритма, так и для отображения.
Здесь мы читаем в первых двух кадрах видеоряда. Мы читаем их как изображения интенсивности, так как цвет не является необходимым для алгоритма стабилизации, и потому, что использование изображений в градациях серого улучшает скорость. Ниже мы показываем оба кадра бок о бок, и мы производим красный-голубой цветовой композит, чтобы проиллюстрировать пиксельное различие между ними. Очевидно, что между двумя рамами имеется большое вертикальное и горизонтальное смещение.
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)');

Наша цель - определить преобразование, которое исправит искажение между двумя кадрами. Мы можем использовать 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');

Затем выбираем соответствия между точками, полученными выше. Для каждой точки мы извлекаем дескриптор быстрой ключевой точки сетчатки (FREAK), центрированный вокруг нее. Стоимость сопоставления между точками - это расстояние Хэмминга, поскольку дескрипторы FREAK являются двоичными. Предполагаемые точки в кадре А и кадре В совпадают. Следует отметить, что ограничение уникальности отсутствует, поэтому точки из кадра 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');

Многие из точечных соответствий, полученных на предыдущем шаге, неверны. Но мы все еще можем получить надежную оценку геометрического преобразования между двумя изображениями, используя алгоритм консенсуса SAmple (MSAC) M-оценщика, который является вариантом алгоритма RANSAC. Алгоритм MSAC реализован в estimateGeometricTransform2D функция. Эта функция, если задан набор соответствий точек, будет искать действительные внутренние соответствия. Из них затем будет получено аффинное преобразование, которое делает inliers из первого набора точек наиболее близким с inliers из второго набора. Это аффинное преобразование будет матрицей 3 на 3 вида:
[a_1 a_3 0; a_2 a_4 0; t_x t_y 1]
Параметры определяют эффект масштаба, поворота и сдвига преобразования, в то время как параметры являются параметрами перемещения. Это преобразование может быть использовано для деформации изображений таким образом, что их соответствующие признаки будут перемещены в то же самое местоположение изображения.
Ограничением аффинного преобразования является то, что оно может только изменять плоскость формирования изображения. Таким образом, это плохо подходит для нахождения общего искажения между двумя кадрами, взятыми из 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);
Ниже представлен цветовой композит, показывающий кадр А, наложенный на повторно проецируемый кадр В, вместе с повторными координатами точек. Результаты превосходны, при этом внутренние соответствия почти точно совпадают. Ядра изображений хорошо выровнены, так что красно-голубой цветовой композит становится почти чисто черно-белым в этой области.
Обратите внимание, что все внутренние соответствия находятся на фоне изображения, а не на переднем плане, который сам по себе не выровнен. Это связано с тем, что фоновые элементы достаточно удалены, чтобы вести себя так, как будто они находятся на бесконечно удаленной плоскости. Таким образом, даже если аффинное преобразование ограничено изменением только плоскости формирования изображения, здесь этого достаточно для выравнивания фоновых плоскостей обоих изображений. Кроме того, если предположить, что фоновая плоскость не перемещалась или существенно не менялась между кадрами, то это преобразование фактически фиксирует движение камеры. Поэтому коррекция для этого стабилизирует видео. Это условие сохраняется до тех пор, пока движение камеры между кадрами достаточно мало, или, наоборот, если частота видеокадров достаточно высока.
figure; showMatchedFeatures(imgA, imgBp, pointsAm, pointsBmp); legend('A', 'B');

Учитывая набор видеокадров 0,1,2..., теперь мы можем использовать вышеупомянутую процедуру для оценки искажения между всеми кадрами Ti Ti + 1 как аффинных преобразований, Hi. Таким образом, совокупное искажение кадра i относительно первого кадра будет результатом всех предшествующих межкадровых преобразований, или
Мы могли бы использовать все шесть параметров аффинного преобразования выше, но, для численной простоты и стабильности, мы решили заново подогнать матрицу как более простое преобразование «масштаб-вращение-перемещение». Это имеет только четыре свободных параметра по сравнению с шестью аффинными преобразованиями: один масштабный коэффициент, один угол и два перевода. Эта новая матрица преобразования имеет вид:
[s*cos(ang) s*-sin(ang) 0;
s*sin(ang) s*cos(ang) 0;
t_x t_y 1]
Мы показываем эту процедуру преобразования ниже, подгоняя полученное выше преобразование с эквивалентом преобразования с вращением шкалы, . Чтобы показать, что ошибка преобразования минимальна, мы повторно проецируем кадр 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');

Теперь применим вышеуказанные шаги для сглаживания видеопоследовательности. Для удобочитаемости вышеупомянутая процедура оценки преобразования между двумя изображениями была помещена в функцию MATLAB ® cvexEstTform. Функция cvexTformToSRT также преобразует общее аффинное преобразование в преобразование scale-rotation-translation.
На каждом этапе вычисляется преобразование между текущими кадрами. Мы подходим под это как s-R-t преобразование, . Затем мы объединяем это кумулятивное преобразование, , которое описывает все движения камеры с первого кадра. Последние два кадра сглаженного видео показаны в видеопроигрывателе в виде красно-голубого композита.
С помощью этого кода вы также можете извлечь условие раннего выхода, чтобы сделать цикл обработки всего видео.
% 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] Тордофф, В; Мюррей, полиция. «Управляемая выборка и консенсус для оценки движения». Европейская конференция n Computer Vision, 2002.
[2] Ли, KY; Чуан, YY; Чен, BY; Ouhyoung, М. «Стабилизация видео с использованием надежных траекторий функций». Национальный Тайваньский университет, 2009 год.
[3] Литвин, А; Конрад, J; Карл, туалет. «Вероятностная стабилизация видео с использованием фильтрации Калмана и мозаики». Симпозиум IS & T/SPIE по электронным изображениям, изображениям и видеосвязи и Proc., 2003.
[4] Мацушита, Y; Офек, Э; Тан, X; Шум, Хэй. «Полнокадровая стабилизация видео». Microsoft ® Research Asia. CVPR 2005.