Richard Smith
Richard Smith

Reputation: 144

Bilinear interpolation anomaly

I wrote a function that takes the subpixels of an image for the purpose of upscaling, and the subpixel is generated by bilinear interpolation, but I am having some weird artifacts.

Here is my code:

public static int getSubPixel(BufferedImage bi, double x, double y) {
    float[] topleft = new Color(bi.getRGB((int) Math.floor(x), (int) Math.floor(y))).getColorComponents(null);
    float[] topright = new Color(bi.getRGB(Math.min(bi.getWidth() - 1, (int) Math.ceil(x)), (int) Math.floor(y))).getColorComponents(null);
    float[] bottomleft = new Color(bi.getRGB((int) Math.floor(x), Math.min(bi.getHeight() - 1, (int) Math.ceil(y)))).getColorComponents(null);
    float[] bottomright = new Color(bi.getRGB(Math.min(bi.getWidth() - 1, (int) Math.ceil(x)), Math.min(bi.getHeight() - 1, (int) Math.ceil(y)))).getColorComponents(null);

    for (int i = 0; i < 3; i++) {
        topleft[i] *= topleft[i];
        topright[i] *= topright[i];
        bottomleft[i] *= bottomleft[i];
        bottomright[i] *= bottomright[i];
    }
    double decX = x % 1;
    double decY = y % 1;
    double inv_DecX = 1 - decX;
    double inv_DecY = 1 - decY;

    float red = (float) Math.sqrt((topleft[0] * inv_DecX + topright[0] * decX) * inv_DecY + (bottomleft[0] * inv_DecX + bottomright[0] * decX) * decY);
    float green = (float) Math.sqrt((topleft[1] * inv_DecX + topright[1] * decX) * inv_DecY + (bottomleft[1] * inv_DecX + bottomright[1] * decX) * decY);
    float blue = (float) Math.sqrt((topleft[2] * inv_DecX + topright[2] * decX) * inv_DecY + (bottomleft[2] * inv_DecX + bottomright[2] * decX) * decY);
    return new Color(red, green, blue).getRGB();
}

This is the result of scaling up a 16x16 image 20 times: original image

upscaled image

As you can see, there is weird streaking going on. I did go out of my way to square the colors before averaging, then taking the square root of the result, but something does not seem right here. Any insight?

PS: I understand functions already exist to do this. This is an educational exercise. I am trying to understand the process by doing it on my own.

Upvotes: 0

Views: 285

Answers (1)

Cris Luengo
Cris Luengo

Reputation: 60444

The stripe artifacts that you are seeing are caused by the linear interpolation scheme. Your implementation is correct (except for the squaring, which is unnecessary and causes the stripes to be stronger in darker regions of the image). This is what I'm seeing with a correct linear interpolation (16x instead of 20x as in the OP, I goofed) but without squaring (note less stripes in the dark blue parts):

linear interpolated image

If you want to get rid of the stripes, use a better interpolation scheme, such as cubic spline interpolation:

cubic spline interpolated image

Upvotes: 1

Related Questions