Bilinear interpolation

我与影子孤独终老i 提交于 2020-01-02 07:51:44

问题


I got this code for scaling image by bilinear interpolation.I know this works but i can't figure out one thing what if the approximated pixel value is an edge(by edge i mean it is in the last row or last column) pixel in the input image then i can i gt a pixel of coordinate (x+1,y+1) ,this should lead to a array index out of range error but no such error occurs why? The code is:

public int[] resizeBilinearGray(int[] pixels, int w, int h, int w2, int h2) {
    int[] temp = new int[w2*h2] ;
    int A, B, C, D, x, y, index, gray ;
    float x_ratio = ((float)(w-1))/w2 ;
    float y_ratio = ((float)(h-1))/h2 ;
    float x_diff, y_diff, ya, yb ;
    int offset = 0 ;
    for (int i=0;i<h2;i++) {
        for (int j=0;j<w2;j++) {
            x = (int)(x_ratio * j) ;
            y = (int)(y_ratio * i) ;
            x_diff = (x_ratio * j) - x ;
            y_diff = (y_ratio * i) - y ;
            index = y*w+x ;

            // range is 0 to 255 thus bitwise AND with 0xff
            A = pixels[index] & 0xff ;
            B = pixels[index+1] & 0xff ;
            C = pixels[index+w] & 0xff ;
            D = pixels[index+w+1] & 0xff ;

            // Y = A(1-w)(1-h) + B(w)(1-h) + C(h)(1-w) + Dwh
            gray = (int)(
                    A*(1-x_diff)*(1-y_diff) +  B*(x_diff)*(1-y_diff) +
                    C*(y_diff)*(1-x_diff)   +  D*(x_diff*y_diff)
                    ) ;

            temp[offset++] = gray ;                                   
        }
    }
    return temp ;
}

回答1:


The reason is that x_ratio and y_ratio are computed incorrectly.

Consider the last pixel of the last row:

i=h2, j=w2 

then:

x = x_ratio * j = (w-1)/w2 * (w2-1) = (w-1) * (w2-1)/w2 <= w-1
y = y_ratio * i = (h-1)/h2 * (h2-1) = (h-1) * (h2-1)/h2 <= h-1

index = y*w+x <= (h-1)*w + (w-1) < w*h

so the index is always less than the size of the pixels array.


Note however, that this is a very dirty hack, which will result in inaccurate results, especially for small images.

You should calculate width/height ratio as follows:

float x_ratio = ((float)w)/w2;
float y_ratio = ((float)h)/h2;

and create a function which converts coordinates to array index - let's name it coord2index. This function takes out-of range coordinates into account and implements a so-called boundary option, which simulates that there are pixels outside the image boundary.

Common options for boundary are:

  • symmetric - pixels outside the image bounds are computed by mirror-reflecting the image at the border. This is probably the best possibility in this case.

  • replicate - pixels outside the image bounds are assumed to be equal to the nearest pixel at the border. This is the simplest way.

  • circular - the image is virtually repeated periodically in all directions. Used for some advanced image processing algorithms; not good for image resizing.




回答2:


I guess the trick is in x_ratio = (float)(w-1))/w2, which computes the ratio as if the original image were one pixel smaller than it's really is. But I'm not sure if this is foolproof and correct (I'd be it isn't - think for example the case w=w2 h=h2 which should give exactly the same image). I really don't like this approach.



来源:https://stackoverflow.com/questions/16341167/bilinear-interpolation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!