Как найти угол поворота стабилизированного видеокадра в Matlab

У меня есть следующий стабилизированный видеокадр, где стабилизация выполняется только вращением и перемещением (без масштабирования):

ори

Как видно на изображении, правая часть изображения симметрична предыдущим пикселям, т. е. черная область после поворота заполняется симметрией. Я добавил красную линию, чтобы обозначить это более четко. красная линия

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

Я, вероятно, могу найти угол грубой силой, но мне интересно, есть ли лучшее и более элегантное решение. Обратите внимание, что значение интенсивности симметричной части не совсем совпадает с исходной частью. Я проверил некоторые значения, например, верхний правый пиксель символа V на клавиатуре [51 49 47] в исходной части, но [50 50 47] в симметричной копии что означает, что соответствующие пиксели не обязательно будут иметь одно и то же значение RGB.

Я реализую это на Matlab или Python, а стабилизация видео выполняется с помощью ffmpeg.

EDIT: у меня есть только стабилизированное видео, у меня нет доступа к исходному видео или файлам, созданным ffmpeg.

Любая помощь/предложение приветствуется,


person smttsp    schedule 07.04.2017    source источник
comment
Лучший способ сделать это — использовать те же преобразования, что и ffmpeg. Я предполагаю, что вы используете плагин VidStab для ffmpeg? Если это так, вы, вероятно, создали файл 'transforms.trf' где-то в процессе. Я бы посмотрел, как отформатирован этот файл, и извлек бы из него значения.   -  person Aaron    schedule 10.04.2017
comment
@ Аарон, я должен был упомянуть, что у меня есть только stabilized video. Теперь обновил вопрос. Я использую плагин deshake и использую команду ffmpeg.exe -i infile -vf deshake -c:v libx264 -crf 0 -preset veryslow outfile.   -  person smttsp    schedule 10.04.2017


Ответы (1)


Пиксель (вероятно) лежит на искомой линии симметрии, если

  • Его (первая/вторая/третья/...) левая и правая точки равны (=> dG, рис. 1 слева)
  • Его (первое/второе/третье/...) левое (или правое) значение отличается (=> dGs, рисунок 1 в середине)

Итак, точки интереса характеризуются высокими значениями |dGs| - |dG| (=> dGs_dG, рис. 1 справа)

Как видно на правом изображении на рисунке 1, все еще существует много ложных срабатываний. Следовательно, преобразование Хафа (рисунок 2 слева) будет использоваться для обнаружения всех точек, соответствующих самой сильной линии (рисунок 2 справа). Зеленая линия действительно является искомой строкой.

Настройка

  • Изменение n: более высокие значения отбрасывают больше ложных срабатываний, но также исключают n граничных пикселей. Этого можно избежать, используя меньшее значение n для граничных пикселей.

  • Изменение порогов: более высокий порог dGs_dG отбрасывает больше ложных срабатываний. Отбрасывание высоких значений dG также может быть интересным для отбрасывания краевых положений в исходном изображении.

  • Априорное знание линии симметрии: используя определение преобразования Хафа, можно отбросить все линии, проходящие через центральную часть изображения.

введите здесь описание изображения

введите здесь описание изображения

Код Matlab, используемый для создания изображений:

I = imread('bnuqb.png');
G = int16(rgb2gray(I));

n = 3; % use the first, second and third left/right point
dG = int16(zeros(size(G) - [0 2*n+2]));
dGs = int16(zeros(size(G) - [0 2*n+2]));
for i=0:n
  dG = dG + abs(G(:, 1+n-i:end-2-n-i) - G(:, 3+n+i:end-n+i));
  dGs = dGs + abs(G(:, 1+n-i:end-2-n-i) - G(:, 2+n:end-n-1));
end
dGs_dG = dGs - dG;
dGs_dG(dGs_dG < 0) = 0;
figure
subplot(1,3,1);
imshow(dG, [])
subplot(1,3,2);
imshow(dGs, [])
subplot(1,3,3);
imshow(dGs_dG, [])

BW = dGs_dG > 0;
[H,theta,rho] = hough(BW);
P = houghpeaks(H,1);
lines = houghlines(BW,theta,rho,P,'FillGap',50000,'MinLength',7);

figure
subplot(1,2,1);
imshow(H, [])
hold on
plot(P(:, 2),P(:, 1),'r.');

subplot(1,2,2);
imshow(I(:, n+2:end-n-1, :))
hold on
max_len = 0;
for k = 1:length(lines)
   xy = [lines(k).point1; lines(k).point2];
   plot(xy(:,1),xy(:,2),'g');
end
person m7913d    schedule 10.04.2017
comment
Спасибо за код. К сожалению, во многих случаях это не работает :( И во многих случаях это довольно близко, но не очень точно. dropbox.com/s/dontiwcwrj4lwwy/img55.PNG?dl=0 и dropbox.com/s/zr0tv2m4i0od911/img125.PNG?dl=0. Но в некоторых случаях работает идеально. Думаю, предполагая, что симметрия не в центре изображения может улучшить производительность. Но есть ли способ свести к минимуму влияние краев на изображения, которыми я поделился? Они определенно увеличат количество ложных срабатываний. - person smttsp; 13.04.2017
comment
Кроме того, на следующих двух изображениях это не совсем точно. dropbox.com/s/vt5mmt4wss0tog4/img4a.PNG?dl=0 — исходное изображение, а его увеличенная версия — dropbox.com/ s/dff1hpprvzoxmq1n/img4b.PNG?dl=0. Возле папки по правому краю увеличенного изображения есть сдвиг на 10 пикселей. Увеличил n, изменений нет. - person smttsp; 13.04.2017
comment
Я добавил некоторые параметры настройки, особенно может быть интересным отбрасывание некоторых областей в преобразовании hough и применение порога к dG. - person m7913d; 14.04.2017
comment
Обратите внимание, что увеличение n также отбрасывает больше граничных пикселей. чего можно избежать, изменив алгоритм, как указано в отредактированном сообщении. На данный момент у меня нет идеи побороть неточность. Может быть, какая-то постобработка немного адаптирует линию, чтобы она лучше совпадала с высокими значениями dGs_dG? Вы уверены, что линия симметрии должна быть прямой? - person m7913d; 14.04.2017
comment
Я согласен с n. но я думаю, что увеличить его на 1-2 может быть немного лучше. Я думаю, что линии должны быть прямыми, потому что вращение является глобальным, поэтому я не вижу причин, по которым они не должны быть прямыми. (Кроме того, я не видел ни одной строки not straight). - person smttsp; 16.04.2017