Accurate Image resizing

102 Views Asked by At

I need to resize an image using bilinear interpolation and create an image pyramid.I will detect corners at the different levels of the pyramid and scale the pixel co-ordinates so that they are relative to the dimensions of the largest image.

If a corner of an object is detected as a corner/keypoint/feature in all the levels,after scaling the corresponding pixel co-ordinates from the different levels so that they fall on the largest image, ideally I would like them to have the same value. Thus when resizing the images, I am trying to be as accurate as possible.

Let's assume I am resizing an image L_n_minus_1 to create a smaller image L_n. My scale factor is "ratio" (ratio>1).

*I cannot use any library.

I can resize using the pseudocode below (which is what I generally find when I search online for resizing algorithms.)

int offset = 0;

for (int i = 0; i < height_of_L_n; i++){

for (int j = 0; j < width_of_L_n; j++){



    //********* This part will differ in the later version I provided below 
    //
    int xSrcInt = (int)(ratio * j);
    float xDiff = ratio * j - xSrcInt;

    int ySrcInt = (int)(ratio * i);
    float yDiff = ratio * i - ySrcInt;

    // The above code will differ in the later version I provided below 



    index = (ySrcInt * width_of_L_n_minus_1 + xSrcInt);

    //Get the 4 pixel values to interpolate
    a = L_n_minus_1[index];
    b = L_n_minus_1[index + 1];
    c = L_n_minus_1[index + width_of_L_n_minus_1];
    d = L_n_minus_1[index + width_of_L_n_minus_1 + 1];

    //Calculate the co-efficients for interpolation
    float c0 = (1 - x_diff)*(1 - y_diff);
    float c1 = (x_diff)*(1 - y_diff);
    float c2 = (y_diff)*(1 - x_diff);
    float c3 = (x_diff*y_diff);

    //half is added for rounding the pixel intensity.
    int intensity = (a*c0) + (b*c1) + (c*c2) + (d*c3) + 0.5;

    if (intensity > 255)
        intensity = 255;

    L_n[offset++] = intensity;

}

}

Or I could use this modified piece of code below :

int offset = 0;

for (int i = 0; i < height_of_L_n; i++){

for (int j = 0; j < width_of_L_n; j++){


    // Here the code differs from the first piece of code
    // Assume pixel centers start from (0.5,0.5). The top left pixel has co-ordinate (0.5,0.5)
    // 0.5 is added to go to the co-ordinates where top left pixel has co-ordinate (0.5,0.5) 
    // 0.5 is subtracted to go to the generally used co-ordinates where top left pixel has co-ordinate (0,0)
    // or in other words map the new co-ordinates to array indices

    int xSrcInt = int((ratio * (j + 0.5)) - 0.5);
    float xDiff = (ratio * (j + 0.5)) - 0.5 - xSrcInt;

    int ySrcInt = int((ratio * (i + 0.5)) - 0.5);
    float yDiff = (ratio * (i + 0.5)) - 0.5 - ySrcInt;

    // Difference with previous code ends here 



    index = (ySrcInt * width_of_L_n_minus_1 + xSrcInt);


    //Get the 4 pixel values to interpolate
    a = L_n_minus_1[index];
    b = L_n_minus_1[index + 1];
    c = L_n_minus_1[index + width_of_L_n_minus_1];
    d = L_n_minus_1[index + width_of_L_n_minus_1 + 1];


    //Calculate the co-efficients for interpolation
    float c0 = (1 - x_diff)*(1 - y_diff);
    float c1 = (x_diff)*(1 - y_diff);
    float c2 = (y_diff)*(1 - x_diff);
    float c3 = (x_diff*y_diff);

    //half is added for rounding the pixel intensity.
    int intensity = (a*c0) + (b*c1) + (c*c2) + (d*c3) + 0.5;

    if (intensity > 255)
        intensity = 255;

    L_n[offset++] = intensity;

}

}

The second piece of code was developed assuming pixel centers having co-ordinates like (0.5, 0.5) as they have in textures. This way the top left pixel will have co-ordinate (0.5, 0.5).

Let us assume :

a 2 by 2 Destination Image is being resized from a 4 by 4 Source Image.

In the first piece of code, it is assumed that the first pixel has co-ordinates (0,0), thus for example my ratio is 2. Then

xSrcInt = (int)(0*2); // 0 ySrcInt = (int)(0*2); // 0

xDiff = (0*2) - 0; // 0 yDiff = (0*2) - 0; // 0

Thus effectively I will just be copying the first pixel value from the source, as c0 will be 1 and c1,c2 and c3 will be 0.

But in the second piece of code I will get

xSrcInt = (int)((0.5*2) - 0.5); // 0; ySrcInt = (int)((0.5*2) - 0.5); // 0;

xDiff = ((0.5*2) - 0.5) - 0; // 0.5; yDiff = ((0.5*2) - 0.5) - 0; // 0.5;

In this case c0,c1,c2 and c3 will all be equal to 0.25. Thus I will be using the 4 pixels at the top left.

Please let me know what do you think and if there is any bug in my second piece of code. As far as visual results go they are working perfectly. But yes I do seem to notice better alignment of keypoints with the second piece of code. But may be that's because I am judging with prejudice :-).

Thanks in advance.

0

There are 0 best solutions below