问题
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?
回答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).
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:
-fx "xxx"
basically says "perform the operationxxx
on the image". In the expression above,u
andv
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 needconvert img1 img2 -fx "(u & NOT v) | (NOT u & v)" img_out
To get the
NOT
(there is a logicalNOT
but no bitwiseNOT
), we remember thatNOT x = 255-x
ifx
is 8-bit. So to getNOT u
we can just do255-u
, assuming imageu
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 inu
andv
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
andv
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!
回答2:
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
回答3:
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"));
回答4:
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.
回答5:
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 ;)
回答6:
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
来源:https://stackoverflow.com/questions/8504882/searching-for-a-way-to-do-bitwise-xor-on-images