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

问题描述 投票:0回答:6

我正在寻找一种方法来在命令行上获取两个图像的按位异或(或以可以在程序或脚本中实现的其他方式)。

这应该会产生与在支持 XOR 混合模式的图片编辑器(Paint.NET、Photoshop 等)中使用 XOR 混合模式相同的最终图片

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

Image A (Seattle, from the Paint.NET documentation)

图像B:

ImageB (an apple, from the paint.net documentation)

那么结果应该是这样的:

Image C (XOR result of above images, from the Paint.NET documentation)

其中有趣的部分当然是,当您再次将图像 C 与图像 B 进行异或时,您将获得图像 A 的精确副本。

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

有人知道如何做到这一点吗?

image image-processing imagemagick xor
6个回答
35
投票

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

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

img1
img2
img_out
分别是两个输入和单个输出文件名)。

说明

它有点难看(我确信比我更懂 ImageMagick 的人可以清理它,但它的工作原理是这样的:

  1. -fx "xxx"
    基本上表示“在图像上执行
    xxx
    操作”。 在上面的表达式中,
    u
    v
    分别代表第一和第二个输入图像。

  2. 现在

    -fx
    按位运算符的方式只有按位AND
    &
    和按位OR
    |
    。 为了重建按位异或,我们需要

    convert img1 img2 -fx "(u & NOT v) | (NOT u & v)" img_out
    
  3. 为了得到

    NOT
    (有逻辑
    NOT
    但没有按位
    NOT
    ),我们记住
    NOT x = 255-x
    if
    x
    是 8 位。 因此,要获得
    NOT u
    ,我们只需执行
    255-u
    ,假设图像
    u
    是 8 位。 因此,ImageMagick 命令将是:

    convert img1.png img2.img -fx "((255-u)&v)|(u&(255-v))" image_xor.png
    
    • 这里的一个问题是,当 ImageMagick 执行

      fx
      时,它会标准化
      u
      v
      范围内
      [0,1]
      中的所有像素,而不是我们期望的
      [0,255]
      ,并对非整数螺丝按位进行操作塞满东西。

    • 因此,我们必须将上述表达式中u

      v
      出现的
      所有
      乘以255(这样按位运算才有效),并在最后除以255以回到范围
      [0,1] 
      ImageMagick 所期望的。

这给了我们原始命令,

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

瞧!


27
投票

我发现图像上需要

xor
,并且 G'MIC 工具适合我。 G'MIC 非常强大,与 Image Magick 一样,但在解决一些棘手的图像处理问题方面值得一看。

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

G'MIC 也可以直接作用于上面发布的图像。

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

寻求帮助,

gmic -h -blend


7
投票

这是我在 Java 中的做法:

一次迭代两个图像的所有像素。 (for 循环 (y) 内的 for 循环 (x))。当然,使用

BufferedImage
。您可以通过以下方式获取像素的颜色:

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

对另一张图像也执行相同操作,并对两种颜色执行异或运算。将结果值存储在与两个输入图像尺寸相同的新 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;
}

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

BufferedImage imageA = ImageIO.read(new File("/home/username/image.png"));

3
投票

如果你想自己做,就逐个像素地做。 如果你想要一个图书馆,我推荐

OpenCV
。这是一个非常好的开源库,在图像处理领域支持大量操作。它支持使用 ^ 运算符直接进行
XOR
。 祝你好运。


1
投票

知道这一点

A XOR B =(A 且非 B)或(非 A 且 B)。

大多数常见的图像处理工具都有 and、or 和 not 操作,剩下的就很简单了:)

在 Python 中工作,您可以使用一个简单的脚本来执行操作,甚至可以将其作为插件添加到 gimp 中;)


1
投票

OpenCV 使用 bitwise_# 在图像和 numpy 图像上具有所有逻辑运算符,其中 # 可以是异或、和、和、不...请参阅 OpenCV - 两个二值图像之间的交集

© www.soinside.com 2019 - 2024. All rights reserved.