4

Consider I have the following a stabilized video frame where stabilization is done by only rotation and translation (no scaling):

ori

As seen in the image, Right-hand side of the image is symmetric of the previous pixels, i.e the black region after rotation is filled with symmetry. I added a red line to indicate it more clearly. red line

I'd like to find the rotation angle which I will use later on. I could have done this via SURF or SIFT features, however, in real case scenario, I won't have the original frame.

I probably can find the angle by brute force but I wonder if there is any better and more elegant solution. Note that, the intensity value of the symmetric part is not precisely the same as the original part. I've checked some values, for example, upper right pixel of V character on the keyboard is [51 49 47] in original part but [50 50 47] in symmetric copy which means corresponding pixels are not guaranteed to be the same RGB value.

I'll implement this on Matlab or python and the video stabilization is done using ffmpeg.

EDIT: I only have stabilized video, don't have access to original video or files produced by ffmpeg.

Any help/suggestion is appreciated,

smttsp
  • 4,011
  • 3
  • 33
  • 62
  • The best way to do it would be to use the same transformations that `ffmpeg` used. I'm presuming you're using the [`VidStab`](https://github.com/georgmartius/vid.stab) plugin for ffmpeg? If so, you probably generated a *'transforms.trf'* file somewhere in the process. I'd look into how this file is formatted, and extract the values from that. – Aaron Apr 10 '17 at 14:13
  • @Aaron I should have mentioned that I only have the `stabilized video`. Now updated the question. I'm using `deshake` plugin and the command I'm using is `ffmpeg.exe -i infile -vf deshake -c:v libx264 -crf 0 -preset veryslow outfile`. – smttsp Apr 10 '17 at 14:24

1 Answers1

6

A pixel (probably) lies on the searched symmetry line if

  • Its (first/second/thrid/...) left and right point are equal (=> dG, Figure 1 left)
  • Its (first/second/thrid/...) left (or right) value is different (=> dGs, Figure 1 middle)

So, the points of interest are characterised by high values for |dGs| - |dG| (=> dGs_dG, Figure 1 right)

As can be seen on the right image of Figure 1, a lot of false positives still exist. Therefore, the Hough transform (Figure 2 left) will be used to detect all the points corresponding to the strongest line (Figure 2 right). The green line is indeed the searched line.

Tuning

  • Changing n: Higher values will discard more false positives, but also excludes n border pixels. This can be avoided by using a lower n for the border pixels.

  • Changing thresholds: A higher threshold on dGs_dG will discard more false positives. Discarding high values of dG may also be interesting to discard edge locations in the original image.

  • A priori knowledge of symmetry line: using the definition of the hough transform, you can discard all lines passing through the center part of the image.

enter image description here

enter image description here

The matlab code used to generate the images is:

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
m7913d
  • 10,244
  • 7
  • 28
  • 56
  • Thanks for the code. Unfortunately, it doesn't work in many cases:( And it is quite close in many cases but not very accurate. https://www.dropbox.com/s/dontiwcwrj4lwwy/img55.PNG?dl=0 and https://www.dropbox.com/s/zr0tv2m4i0od911/img125.PNG?dl=0. But it works perfect in some cases. I think, assuming that the symmetry is not in the center of the image might improve performance. But is there a way to minimize the effect of edges on the images I shared. They will definitely increase false positive. – smttsp Apr 13 '17 at 18:13
  • Also, in the following two images, it is not totally accurate. https://www.dropbox.com/s/vt5mmt4wss0tog4/img4a.PNG?dl=0 is the original image and its zoomed version is https://www.dropbox.com/s/dff1hprvzoxmq1n/img4b.PNG?dl=0. Near the folder on the right edge of the zoomed image, there are 10 pixels shift. I increased `n`, still there is no change. – smttsp Apr 13 '17 at 18:20
  • I added some tuning options, especially discarding some regions in the hough transform and applying a threshold on `dG` may be interesting. – m7913d Apr 14 '17 at 08:06
  • Note that increasing `n` also discard more border pixels. which may be avoided by changing the algorithm as pointed out in the edited post. I do not have an idea to overcome the inaccuracy at the moment. Maybe some post-processing to adapt the line slightly to better coincides with the high values of `dGs_dG`? Are you sure that the symmetry line should be a straight line? – m7913d Apr 14 '17 at 08:17
  • I agree with the `n`. but I think increasing it by 1-2 might be slightly better. I think the lines should be straight because the rotation is global, so I don't see any reason why it should not be straight. (Also, I haven't seen any `not straight` line). – smttsp Apr 16 '17 at 00:15