Incorrect result of image subtraction

前端 未结 3 1533
傲寒
傲寒 2021-01-12 12:31

I wanted to subtract two images pixel by pixel to check how much they are similar. Images have the same size one is little darker and beside brightness they don\'t differ. B

3条回答
  •  离开以前
    2021-01-12 13:31

    The problem here is that you can't subtract the colors direcly. Each pixel is represented by one int value. This int value consists of 4 bytes. These 4 bytes represent the color components ARGB, where

    A = Alpha
    R = Red
    G = Green
    B = Blue
    

    (Alpha is the opacity of the pixel, and always 255 (that is, the maximum value) in BMP images).

    Thus, one pixel may be represented by

    (255, 0, 254, 0)

    When you subtract another pixel from this one, like (255, 0, 255, 0), then the third byte will underflow: It would become -1. But since this is part of ONE integer, the resulting color will be something like

    (255, 0, 254, 0) - 
    (255, 0, 255, 0) = 
    (255, 255, 255, 0)
    

    and thus, be far from what you would expect in this case.


    The key point is that you have to split your color into the A,R,G and B components, and perform the computation on these components. In the most general form, it may be implemented like this:

    int argb0 = image0.getRGB(x, y);
    int argb1 = image1.getRGB(x, y);
    
    int a0 = (argb0 >> 24) & 0xFF;
    int r0 = (argb0 >> 16) & 0xFF;
    int g0 = (argb0 >>  8) & 0xFF;
    int b0 = (argb0      ) & 0xFF;
    
    int a1 = (argb1 >> 24) & 0xFF;
    int r1 = (argb1 >> 16) & 0xFF;
    int g1 = (argb1 >>  8) & 0xFF;
    int b1 = (argb1      ) & 0xFF;
    
    int aDiff = Math.abs(a1 - a0);
    int rDiff = Math.abs(r1 - r0);
    int gDiff = Math.abs(g1 - g0);
    int bDiff = Math.abs(b1 - b0);
    
    int diff = 
        (aDiff << 24) | (rDiff << 16) | (gDiff << 8) | bDiff;
    result.setRGB(x, y, diff);
    

    Since these are grayscale images, the computations done here are somewhat redundant: For grayscale images, the R, G and B components are always equal. And since the opacity is always 255, it does not have to be treated explicitly here. So for your particular case, it should be sufficient to simplify this to

    int argb0 = image0.getRGB(x, y);
    int argb1 = image1.getRGB(x, y);
    
    // Here the 'b' stands for 'blue' as well
    // as for 'brightness' :-)
    int b0 = argb0 & 0xFF;
    int b1 = argb1 & 0xFF;
    int bDiff = Math.abs(b1 - b0);
    
    int diff = 
        (255 << 24) | (bDiff << 16) | (bDiff << 8) | bDiff;
    result.setRGB(x, y, diff);
    

提交回复
热议问题