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 the same final picture as using the XOR Blending mode in picture editors that support it (Paint.NET, Photoshop, etc)
As an example, say I have Image A:
and Image B:
then the result should look like:
The fun part of this is of course, that when you XOR image C with image B again, you will get an exact copy of image A.
Now, I have been looking all over the internet for a way to do this programmatically, but I have found nothing. Even ImageMagick does not support doing a bitwise XOR on images.
Does sombebody know a way to do this?
The XOR (and similarly the XNOR) operator typically takes two binary or graylevel images as input, and outputs a third image whose pixel values are just those of the first image, XORed with the corresponding pixels from the second.
We apply the bitwise XOR on Line 35 using the cv2. bitwise_xor function. An XOR operation is true if and only if one of the two pixels is greater than zero, but both pixels cannot be greater than zero.
A binary image is one that consists of pixels that can have one of exactly two colors, usually black and white. Binary images are also called bi-level or two-level, Pixelart made of two colours is often referred to as 1-Bit or 1bit. This means that each pixel is stored as a single bit—i.e., a 0 or 1.
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).
It's a bit ugly (I'm sure someone with more ImageMagick-fu than me could clean it up but it works like this:
-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.
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
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!
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With