Searching for a way to do Bitwise XOR on images

前端 未结 6 1636
Happy的楠姐
Happy的楠姐 2021-01-31 09:42

I am looking for a way to get the Bitwise XOR of two images on the command line(or in another way that can be implemented in a program or script).

This should result in

相关标签:
6条回答
  • 2021-01-31 10:22

    Here is how I would do in Java:

    Iterate over all the pixels of the two images at once. (for loop (x) inside a for loop (y)). Of course, use a BufferedImage. You can get the color of the pixel by doing:

    int color = img.getRGB(x, y);
    

    Do the same for the other image as well and perform the xor operation on the two colors. Store the resulting value in a new BufferedImage with the same dimensions as the two input images.

    Here is some sample code:

    public static BufferedImage xorEffect(BufferedImage imageA, BufferedImage imageB) {
        if (imageA.getWidth() != imageB.getWidth() ||
            imageA.getHeight() != imageB.getHeight())
        {
            throw new IllegalArgumentException("Dimensions are not the same!");
        }
        BufferedImage img = new BufferedImage(imageA.getWidth(),
                                              imageA.getHeight(),
                                              BufferedImage.TYPE_INT_ARGB_PRE);
    
        for (int y = 0; y < imageA.getHeight(); ++y) {
            for (int x = 0; x < imageA.getWidth(); ++x) {
               int pixelA = imageA.getRGB(x, y);
               int pixelB = imageB.getRGB(x, y);
               int pixelXOR = pixelA ^ pixelB;
               img.setRGB(x, y, pixelXOR);
            }
        }
        return img;
    }
    

    To load an image from a file use:

    BufferedImage imageA = ImageIO.read(new File("/home/username/image.png"));
    
    0 讨论(0)
  • 2021-01-31 10:22

    If you want to do yourself, do it pixel by pixel. If you want a library, I recommend OpenCV. This is very nice and open source library with huge operations supported in image processing area. It supports direct XOR using ^ operator. Good Luck.

    0 讨论(0)
  • 2021-01-31 10:24

    Knowing that

    A XOR B = (A AND NOT B) OR (NOT A AND B).

    and that most of common image processing tools do have and, or and not operations the rest is quite easy :)

    Working in Python, you could have a simple script performing the operation and even adding it as a plugin in the gimp ;)

    0 讨论(0)
  • 2021-01-31 10:32

    I found a need for xor on an image and the G'MIC tool works for me. G'MIC is incredibly powerful, as is Image Magick, but worth a look for solving some tough image processing problems.

    gmic a.png b.png -blend xor -o result.png
    

    G'MIC also works directly on the images posted above.

    gmic http://i.stack.imgur.com/Ws6e8.png http://i.stack.imgur.com/hoBIM.png -blend xor -o result.png
    

    For help,

    gmic -h -blend
    

    0 讨论(0)
  • 2021-01-31 10:44

    OpenCV has all the logical operators on images and numpy images using bitwise_# Where # can be xor, and, and, not ... See OpenCV - Intersection between two binary images

    0 讨论(0)
  • 2021-01-31 10:46

    ImageMagick can do it, although it's a bit convoluted. One way is:

    convert img1 img2 -fx "(((255*u)&(255*(1-v)))|((255*(1-u))&(255*v)))/255" img_out
    

    (img1,img2,img_out are the two input and single output file names respectively).

    Explanation

    It's a bit ugly (I'm sure someone with more ImageMagick-fu than me could clean it up but it works like this:

    1. -fx "xxx" basically says "perform the operation xxx on the image". In the expression above, u and v stand for the first and second input images respectively.

    2. Now, -fx only has bitwise AND & and bitwise OR | in the way of bitwise operators. To reconstruct bitwise XOR, we need

      convert img1 img2 -fx "(u & NOT v) | (NOT u & v)" img_out
      
    3. To get the NOT (there is a logical NOT but no bitwise NOT), we remember that NOT x = 255-x if x is 8-bit. So to get NOT u we can just do 255-u, assuming image u is 8-bit. Hence, the ImageMagick command would be:

      convert img1.png img2.img -fx "((255-u)&v)|(u&(255-v))" image_xor.png
      
      • The one problem here is that when ImageMagick does fx it normalises all the pixels in u and v in the range [0,1] instead of [0,255] as we expect, and doing bitwise on non-integers screws stuff up.

      • Hence, we have to multiply all occurrences of u and v in the above expression by 255 (so the bitwise operations work), and divide by 255 at the very end to get back in the range [0,1] that ImageMagick expects.

    This gives us the original command,

    convert img1 img2 -fx "(((255*u)&(255*(1-v)))|((255*(1-u))&(255*v)))/255" img_out
    

    Voila!

    0 讨论(0)
提交回复
热议问题