寻找一种在图像上进行按位异或的方法

Qqw*_*qwy 18 image imagemagick image-processing xor

我正在寻找一种在命令行上获得两个图像的Bitwise XOR的方法(或者以可以在程序或脚本中实现的另一种方式).

这应该导致与支持它的图片编辑器中使用XOR混合模式相同的最终图片(Paint.NET,Photoshop等)

举个例子,假设我有图像A:

图片A(西雅图,来自paint.net文档

图像B:

ImageB(Apple,来自paint.net文档)

那么结果应该是这样的:

图像C(以上图像的Xor结果,来自paint.net文档)

当然,有趣的是,当您再次使用图像B对图像C进行异或时,您将获得图像A的精确副本.

现在,我一直在互联网上查找以编程方式执行此操作的方法,但我一无所获.甚至ImageMagick也不支持对图像进行按位异或.

sombebody知道这样做的方法吗?

mat*_*fee 23

ImageMagick可以做到这一点,虽然它有点复杂.一种方法是:

convert img1 img2 -fx "(((255*u)&(255*(1-v)))|((255*(1-u))&(255*v)))/255" img_out
Run Code Online (Sandbox Code Playgroud)

(img1,img2,img_out分别是两个输入和单输出的文件名).

说明

这有点难看(我敢肯定有人比我更多的ImageMagick-fu可以清理它,但它的工作原理如下:

  1. -fx "xxx"基本上说" xxx对图像进行操作".在上面的表达,uv分别代表第一和第二输入图像.

  2. 现在,-fx在按&|运算符的方式中只有按位AND 和按位OR .要重建按位异或,我们需要

    convert img1 img2 -fx "(u & NOT v) | (NOT u & v)" img_out
    
    Run Code Online (Sandbox Code Playgroud)
  3. 为了得到NOT(有一个逻辑NOT但没有按位NOT),我们记得NOT x = 255-x 如果 x是8位.所以NOT u我们可以做到255-u,假设图像u是8位.因此,ImageMagick命令将是:

    convert img1.png img2.img -fx "((255-u)&v)|(u&(255-v))" image_xor.png
    
    Run Code Online (Sandbox Code Playgroud)
    • 这里的一个问题是,当ImageMagick的做fx它在正常化的所有像素uv范围内[0,1],而不是[0,255]像我们预期的,并且在非整数螺丝做按位东西了.

    • 因此,我们必须将所有出现的uv在上面的表达式中乘以255(因此按位运算起作用),并在最后除以255以回到[0,1]ImageMagick期望的范围内.

这给了我们原始命令,

convert img1 img2 -fx "(((255*u)&(255*(1-v)))|((255*(1-u))&(255*v)))/255" img_out
Run Code Online (Sandbox Code Playgroud)

瞧!

  • 看起来棒极了;D. 你的代码中有一个小错误很难(第二个你应该是av)。修复。然而它确实需要很长时间才能运行...^^' (2认同)

Rob*_*abs 14

我发现需要xor一个图像,G'MIC工具适合我.G'MIC非常强大,Image Magick也是如此,但值得一试解决一些棘手的图像处理问题.

gmic a.png b.png -blend xor -o result.png
Run Code Online (Sandbox Code Playgroud)

G'MIC也直接在上面发布的图像上工作.

gmic http://i.stack.imgur.com/Ws6e8.png http://i.stack.imgur.com/hoBIM.png -blend xor -o result.png
Run Code Online (Sandbox Code Playgroud)

求助,

gmic -h -blend
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 很遗憾只能选择一个答案,因为这个 gmic 看起来是一个很棒的工具。(我选择了我最初最终使用的答案,我应该选择但两年前忘记选择了)。谢谢你这么棒的回答! (2认同)

Mar*_*aux 5

以下是我在Java中的表现:

一次迭代两个图像的所有像素.(for循环(y)中的循环(x)).当然,用一个BufferedImage.您可以通过执行以下操作获取像素的颜色:

int color = img.getRGB(x, y);
Run Code Online (Sandbox Code Playgroud)

对其他图像执行相同操作,并对两种颜色执行xor操作.将结果值存储在与两个输入图像具有相同尺寸的新BufferedImage中.

以下是一些示例代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

要从文件加载图像,请使用:

BufferedImage imageA = ImageIO.read(new File("/home/username/image.png"));
Run Code Online (Sandbox Code Playgroud)