【问题标题】:Searching for a way to do Bitwise XOR on images寻找对图像进行按位异或的方法
【发布时间】:2012-01-20 06:01:46
【问题描述】:

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

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

例如,假设我有 图片 A:

图片 B:

那么结果应该是这样的:

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

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

有人知道这样做的方法吗?

【问题讨论】:

    标签: image image-processing imagemagick xor


    【解决方案1】:

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

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

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

    说明

    它有点难看(我相信 ImageMagick-fu 比我多的人可以清理它,但它的工作原理是这样的:

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

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

      convert img1 img2 -fx "(u & NOT v) | (NOT u & v)" img_out
      
    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
      
      • 这里的一个问题是,当 ImageMagick 执行fx 时,它会将uv 范围内的所有像素归一化[0,1],而不是我们期望的[0,255],并按位执行非整数搞砸了。

      • 因此,我们必须将上述表达式中出现的uv所有 乘以255(所以按位运算有效),然后除以255结束回到 ImageMagick 期望的[0,1] 范围内。

    这给了我们原始的命令,

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

    瞧!

    【讨论】:

    • 看起来棒极了;D。您的代码中存在一个小错误(第二个 u 应该是 v)。修复。然而,它确实需要 AGES 才能运行...... ^^'
    • ta,可惜运行时间太长了(我只在你拥有的那些婴儿图像上尝试过)。编写一些代码仍然是最快的,imagemagick 中的-fx 确实以速度较慢而闻名。
    • ImageMagick-7.0.11-Q8>magick.exe 1.png 2.png -fx "u&(1-v)|(1-u)&v" img.png (测试 1 位和 8 位图像)
    【解决方案2】:

    我发现需要在图像上使用xor,而G'MIC 工具对我有用。 G'MIC 和 Image Magick 一样强大,但在解决一些棘手的图像处理问题时值得一看。

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

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

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

    寻求帮助,

    gmic -h -blend
    

    【讨论】:

    • 很遗憾只能选择一个答案,因为这个 gmic 看起来是个很棒的工具。 (我选择了我最初最终使用的答案,我应该有,但两年前忘记选择了)。感谢您的精彩回答!
    【解决方案3】:

    这是我在 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"));
    

    【讨论】:

    • 您可能想使用 BufferedImage.TYPE_INT_RGB,这样 alpha 就不会造成差异。
    【解决方案4】:

    如果你想自己做,就一个像素一个像素地做。 如果你想要一个图书馆,我推荐OpenCV。这是一个非常好的开源库,在图像处理领域支持大量操作。它支持使用^ 运算符直接XOR。 祝你好运。

    【讨论】:

      【解决方案5】:

      知道

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

      而且大多数常见的图像处理工具都有和,或者和不操作,其余的很容易:)

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

      【讨论】:

      • 顺便说一句,我可能有一个使用 Python 和 opencv 的快速且(以某种方式)优雅的实现。如果需要,我可以把它寄到这里;)
      【解决方案6】:

      OpenCV 使用 bitwise_# 对图像和 numpy 图像具有所有逻辑运算符,其中 # 可以是异或,并且,并且,不是...参见OpenCV - Intersection between two binary images

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-03
        • 1970-01-01
        • 1970-01-01
        • 2022-10-03
        • 2019-09-29
        • 1970-01-01
        • 1970-01-01
        • 2010-10-31
        相关资源
        最近更新 更多