Reputation: 1152
I am having difficulty implementing Bilinear Interpolation of a rotated image. The image is represented as doubles in a 2D matrix. Below is the code I have been using. The image rotates correctly by the desired angle, however the interpolation does not seem to eliminate the 'jaggedness' of the output image as desired.
Can anyone identify the issue with my code?
// DimX & DimY are dimensions of input Image (Which has padded space for rotation)
// radian = angle as rad (2*PI*{angle in deg})/360)
// COGPosX & COGPosY are the Centre of Gravity pos for the Input Matrix
// SliceMatrix is the un-rotated input Matrix
// double cosine,sine,f1,f2,fval,p1,p2,p3,p4,rotX,rotY,xfloor,yfloor;
// double *sliceMatrix, *rotationMatrixInter;
// int x,y,dimX,dimY,COGPosX,COGPosY,rotatedX,rotatedY;
cosine = (double)cos(radian);
sine = (double)sin(radian);
for(y=0;y<dimY;y++)
{
for(x=0;x<dimX;x++)
{
// Calculate rotated Matrix positions
rotatedX=(double)((x-COGPosX)*cosine)-((y-COGPosY)*sine)+COGPosX;
rotatedY=(double)((x-COGPosX)*sine)+((y-COGPosY)*cosine)+COGPosY;
rotX = (int)floor(rotatedX);
rotY = (int)floor(rotatedY);
xfloor = floor(rotatedX);
yfloor = floor(rotatedY);
if(rotX >=0 && rotY < dimX-1 && rotY >=0 && rotY < dimY-1 )
{
// BLI Calculation
p1 = sliceMatrix[rotX+(dimX*rotY)]; // 0,0
p2 = sliceMatrix[rotX+(dimX*(rotY+1))]; // 0,1
p3 = sliceMatrix[(rotX+1)+(dimX*rotY)]; // 1,0
p4 = sliceMatrix[(rotX+1)+(dimX*(rotY+1))]; // 1,1
f1 = p1 + (p3-p1)*(rotatedX-xfloor);
f2 = p2 + (p4-p2)*(rotatedX-xfloor);
fval = f1 + (f2-f1)*(rotatedY-yfloor);
rotationMatrixInter[x+(dimX*y)]= fval;
}
}
}
Upvotes: 1
Views: 2621
Reputation: 17595
Apparently you don't really interpolate as expected. rotatedX
and rotatedY
are of type int
; if you cast them to double, they remain integral values and the denominators
((double)(rotatedX+1.0)-(double)rotatedX))
((double)(rotatedX+1.0)-(double)rotatedX))
cancel out to be 1.0
, which means that no real interpolation as desired takes place, but f1
and f2
actually get assigned p3
and p4
respectively. The variables rotatedX
and rotatedY
would have to be of type double
. After rotation, they would have to be rounded down and up (or just round down and add one) to get the four positions to sample the image data from, and the difference to the rounded values would govern the interpolation. This could be done as follows, where floor
is supposed to round down.
double xfloor = floor(rotatedX);
double yfloor = floor(rotatedY);
f1 = p1 + (p3-p1)*(rotatedX-xfloor);
f2 = p2 + (p4-p2)*(rotatedX-xfloor);
fval = f1 + (f2-f1)*(rotatedY-yfloor);
Upvotes: 1