Этот пример показывает, как стабилизировать видео, которое было записано с нервной платформы. Один способ стабилизировать видео состоит в том, чтобы отследить существенную функцию в изображении и использовать это в качестве точки привязки, чтобы уравновесить все возмущения относительно него. Эта процедура, однако, должна быть загружена со знанием того, где такая существенная функция находится в первом кадре видео. В этом примере мы исследуем метод видео стабилизации, которая работает без любого такого априорного ведома. Это вместо этого автоматически ищет "фоновую плоскость" в видео последовательности и использует ее наблюдаемое искажение, чтобы исправить для движения камеры.
Этот алгоритм стабилизации включает два шага. Во-первых, мы определяем аффинные преобразования изображений между всеми соседними кадрами видео последовательности с помощью функции estimateGeometricTransform
, примененной к соответствиям точки между двумя изображениями. Во-вторых, мы деформируем кадры видео, чтобы достигнуть стабилизированного видео. Мы будем использовать Computer Vision Toolbox™, и для алгоритма и для отображения.
Этот пример подобен Видео Примеру Стабилизации. Основное различие - то, что Видео Примеру Стабилизации дают область, чтобы отследить, в то время как этому примеру не дают такого знания. Оба примера используют то же видео.
Здесь мы читаем в первых двух кадрах видео последовательности. Мы читаем их, когда интенсивность отображает, поскольку цвет не необходим для алгоритма стабилизации, и потому что использование полутоновых изображений улучшает скорость. Ниже мы показываем оба кадра рядом, и мы производим красно-голубой цветной составной объект, чтобы проиллюстрировать мудрое пикселем различие между ними. Между двумя кадрами существует, очевидно, большое вертикальное и горизонтальное смещение.
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)');
Наша цель состоит в том, чтобы определить преобразование, которое исправит для искажения между двумя кадрами. Мы можем использовать функцию estimateGeometricTransform
для этого, которое возвратит аффинное преобразование. Как введено мы должны предоставить этой функции набор соответствий точки между двумя кадрами. Чтобы сгенерировать эти соответствия, мы сначала собираем интересные места из обоих кадров, затем избранные вероятные соответствия между ними.
На этом шаге мы производим эти точки кандидата для каждого кадра. Чтобы иметь лучшую возможность, что эти точки будут иметь соответствующие точки в другом кадре, мы хотим точки вокруг существенных функций изображений, таких как углы. Для этого мы используем функцию 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');
Затем мы выбираем соответствия между точками, выведенными выше. Для каждой точки мы извлекаем Быструю Сетчатку Keypoint (ПЯТНО) дескриптор, сосредоточенный вокруг этого. Стоимостью соответствия, которую мы используем между точками, является Расстояние Хемминга, поскольку дескрипторы ПЯТНА являются двоичным файлом. Точки в кадре A и кадре B являются соответствующими предполагаемо. Обратите внимание на то, что нет никакого ограничения уникальности, таким образом, точки от кадра B могут соответствовать нескольким точкам в кадре A.
% Extract FREAK descriptors for the corners
[featuresA, pointsA] = extractFeatures(imgA, pointsA);
[featuresB, pointsB] = extractFeatures(imgB, pointsB);
Совпадайте с функциями, которые были найдены в токе и предыдущих кадрах. Поскольку дескрипторы ПЯТНА являются двоичным файлом, функция matchFeatures
использует Расстояние Хемминга, чтобы найти соответствующие точки.
indexPairs = matchFeatures(featuresA, featuresB); pointsA = pointsA(indexPairs(:, 1), :); pointsB = pointsB(indexPairs(:, 2), :);
Изображение ниже показов, которые, добавил тот же цветной составной объект, данный выше, но является точками от кадра в красном и точках от кадра B в зеленом. Желтые линии проведены между точками, чтобы показать соответствия, выбранные вышеупомянутой процедурой. Многие из этих соответствий правильны, но существует также значительное количество выбросов.
figure; showMatchedFeatures(imgA, imgB, pointsA, pointsB); legend('A', 'B');
Многие соответствия точки, полученные на предыдущем шаге, являются неправильными. Но мы можем все еще вывести устойчивую оценку геометрического преобразования между двумя изображениями с помощью Демонстрационного Согласия M-средства-оценки (MSAC) алгоритм, который является вариантом алгоритма RANSAC. Алгоритм MSAC реализован в функции estimateGeometricTransform
. Эта функция, когда дали набор соответствий точки, будет искать допустимые inlier соответствия. От них это затем выведет аффинное преобразование, которое делает inliers из первого соответствия набора точек наиболее тесно с inliers от второго набора. Это аффинное преобразование будет 3х3 матрицей формы:
[a_1 a_3 0; a_2 a_4 0; t_x t_y 1]
Параметры задайте шкалу, вращение и эффекты сдвига преобразования, в то время как параметры параметры перевода. Это преобразование может использоваться, чтобы деформировать изображения, таким образом, что их соответствующие функции будут перемещены в то же расположение изображения.
Ограничение аффинного преобразования - то, что оно может только изменить плоскость обработки изображений. Таким образом это является неподходящим к нахождению общего искажения между двумя кадрами, взятыми 3-D сцены, такой как с этим видео, снятым от движущегося автомобиля. Но это действительно работает при определенных обстоятельствах, которые мы опишем вскоре.
[tform, pointsBm, pointsAm] = estimateGeometricTransform(... pointsB, pointsA, 'affine'); imgBp = imwarp(imgB, tform, 'OutputView', imref2d(size(imgB))); pointsBmp = transformPointsForward(tform, pointsBm.Location);
Ниже цветной кадр показа составного объекта наложенный с повторно спроектированным кадром B, наряду с повторно спроектированными соответствиями точки. Результаты превосходны с inlier соответствиями, почти точно совпадающими. Ядра изображений оба хорошо выравниваются, такие, что красно-голубой цветной составной объект становится почти чисто черно-белым в той области.
Отметьте, как inlier соответствия - все в фоновом режиме изображения, не на переднем плане, который самом не выравнивается. Это вызвано тем, что фоновые функции достаточно удалены, что они ведут себя, как будто они были на бесконечно удаленной плоскости. Таким образом, даже при том, что аффинное преобразование ограничивается изменением только плоскости обработки изображений, здесь который достаточен, чтобы выровнять фоновые плоскости обоих изображений. Кроме того, если мы принимаем, что фоновая плоскость не переместилась или значительно изменилась между кадрами, затем это преобразование на самом деле получает движение камеры. Поэтому исправление для этого стабилизирует видео. Это условие будет содержать, пока движение камеры между кадрами является достаточно маленьким, или, с другой стороны, если частота видеокадров достаточно высока.
figure; showMatchedFeatures(imgA, imgBp, pointsAm, pointsBmp); legend('A', 'B');
Учитывая набор кадров видео , мы можем теперь использовать вышеупомянутую процедуру, чтобы оценить искажение между всеми кадрами и как аффинные преобразования, . Таким образом совокупное искажение кадра относительно первого кадра будет продукт всех предыдущих межкадровых преобразований, или
Мы могли использовать все шесть параметров аффинного преобразования выше, но, для числовой простоты и устойчивости, мы принимаем решение переоборудовать матрицу, когда более простой перевод вращения шкалы преобразовывает. Это имеет только четыре свободных параметра по сравнению с шестью полного аффинного преобразования: один масштабный коэффициент, один угол и два перевода. Это новое преобразовывает матрицу, имеет форму:
[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® cvexEstStabilizationTform. Функция cvexTformToSRT также преобразовывает общее аффинное преобразование в перевод вращения шкалы, преобразовывают.
На каждом шаге мы вычисляем преобразование между существующими кадрами. Мы соответствуем этому, когда s-R-t преобразовывает, . Затем мы комбинируем это совокупное преобразование, , который описывает все движение камеры начиная с первого кадра. Последние два кадра сглаживавшего видео показывают в Видеоплеере как красно-голубой составной объект.
С этим кодом можно также вынуть раннее выходное условие заставить цикл обработать целое видео.
% 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] Тордофф, B; Мюррей, DW. "Ведомая выборка и согласие для оценки движения". Европейская Конференция n Компьютерное зрение, 2002.
[2] Ли, KY; Чуан, YY; Чен, BY; Ouhyoung, M. "Видео Стабилизация с помощью Устойчивых Траекторий Функции". Национальный университет Тайваня, 2009.
[3] Литвин, A; Конрад, J; Карл, WC. "Вероятностная видео стабилизация с помощью Кальмана, фильтрующего и mosaicking". Симпозиум IS&T/SPIE по Электронной Обработке изображений, Изображению и Video Communications и Proc., 2003.
[4] Matsushita, Y; Ofek, E; сильный запах, X; Shum, HY. "Стабилизация видео полного кадра". Microsoft® Research Asia. CVPR 2005.