For a project, I have a matrix<float>
which is rotated few degrees. I have no control over this process (assume it is using nearest neighbour), I want to reverse this rotation operation and obtain the initial matrix (or a matrix very close to it).
My initial assumption was if I rotate the rotated matrix with -angle
and crop the middle part, I'd have the original matrix but the results indicate the quality drops dramatically.
Consider my original matrix (the first image in the figure) is 10x10 matrix from 1 to 100. I rotate it +10 degrees, then -10 degrees. The second image in the figure is my resulting matrix. Then I crop from the middle of the second matrix and correlate it with the initial matrix.
I tested this with 1000 random matrix of 1000*1000; when I rotate -10 degrees with bicubic
or bilinear
interpolation, the average correlation result is around 0.37 whereas nearest neighbor
is 0.25.
If both interpolations are bilinear
or bicubic
, then the correlation result is around 0.45-0.5.
I'm wondering if there is a way to minimize the loss caused by interpolation. Note that in the real experiment I don't have the original image, I'm just estimating rotation angle, so there is another performance drop caused by the precision of the rotation angle estimation. I searched online but couldn't find anything about it.
Here is my simple test code in matlab,
res = 0;
for i = 0:1000
a = uint8(rand(1000,1000)*255);
arr = imrotate(imrotate(a,10, 'bicubic'), -10, 'bicubic');
[r1,c1] = size(a);
[r2,c2] = size(arr);
rd = ceil((c2-c1)/2);
cd = ceil((r2-r1)/2);
c_arr = arr(cd:end-cd, rd:end-rd);
res = res+corr2(a, c_arr);
end
res/1000
I did small test in C++ on your P1.csv
750x1000
matrix. I rotated it by+10deg
then back by-10deg
with bilinear interpolation around matrix center.Resulting correlation (on the
749x749
mid square of result) is0.8275936
So either you are not correlating the same data (perhaps some offset between matrices) or you are truncating the result somehow. For example I make this from my integer matrix rotation code and while forget to remove integer truncating the correlation was around0.3
which is similar to your claims.As I do not use Matlab here my C++ source you can try to port or check with your implementations:
matrix A
is just dynamic 2D array (I busted for this) likefloat A[A.xs][A.ys];
wherexs,ys
is the size.A.resize(xs,ys)
will resize matrixA
to new size. Here source:The test looks like this:
Due to bilinear interpolation the rotated cells are bleeding to neighboring cells so if you need to rotate many times (for example to find out the unknown angle) then you should always rotate the original matrix instead of applying rotation multiple times on sub-result matrix.
Here preview for your P1
on the left original matrix
A
in the middle rotated matrixB
by+10deg CW
and on right matrixC
rotated back by-10deg CW
. Blue pixels are positive and red pixels are negative values. The green rectangle is correlated area (sqrt of square overlapped area)[Edit1] I play with the coloring a bit
let
a0=-13.487; a1=9.3039;
be the min and max values from yourA
matrix. Then to compute RGB color from any value fromA,B
orC
I used this:And here the recolored result:
As you can see there are Features that could be used to detect booth the rotation angle and center of rotation ... Just locate/cross match the holes in
A
andB
and then compute the difference angle. After rotation compute offset and you should get all you need ...