2D Matrix Rotation with Bilinear Interpolation

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

Answers (1)

Codor
Codor

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

Related Questions