Поиск способа выполнения Побитового XOR на изображениях

Я ищу способ получить Побитовое XOR двух изображений в командной строке (или по-другому, которые могут быть реализованы в программа или script).

Это должно привести к тому же финальному изображению, что и использование режима смешивания XOR в редакторах изображений, которые его поддерживают (Paint.NET, Photoshop и т.д.).

В качестве примера, скажем, у меня Изображение A:

Image A(Seattle, from the paint.net documentation

и Изображение B:

ImageB(Apple, from the paint.net documentation)

тогда результат должен выглядеть так:

Image C(Xor result of above images, from the paint.net documentation)

Интересной частью этого является, конечно, то, когда вы снова получите изображение XOR C с изображением B, вы получите точную копию изображения A.

Теперь я искал по всему Интернету способ сделать это программно, но я ничего не нашел. Даже 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, чем я, мог бы его очистить, но он работает следующим образом:

  • -fx "xxx" в основном говорит "выполнить операцию xxx на изображении". В приведенном выше выражении u и v обозначают первое и второе входные изображения соответственно.

  • Теперь -fx имеет только побитовый AND & и побитовый OR | в качестве побитовых операторов. Для восстановления побитового XOR нам нужно

    convert img1 img2 -fx "(u & NOT v) | (NOT u & v)" img_out
    
  • Чтобы получить 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, он нормализует все пиксели в u и v в диапазоне [0,1] вместо [0,255], как мы ожидаем, и выполняем побитовое на не целые винты.

    • Следовательно, мы должны умножить все вхождения u и v в приведенном выше выражении на 255 (так что побитовые операции работают) и делить на 255 на самом end, чтобы вернуться в диапазон [0,1], который ожидает ImageMagick.

Это дает нам исходную команду

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

Voila!

Ответ 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

введите описание изображения здесь

Ответ 3

Вот как я буду делать в Java:

Итерации по всем пикселям двух изображений одновременно. (для цикла (x) внутри цикла for (y)). Конечно, используйте BufferedImage. Вы можете получить цвет пикселя, выполнив:

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

Сделайте то же самое для другого изображения и выполните операцию 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;
}

Чтобы загрузить изображение из файла, используйте:

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

Ответ 4

Зная, что

A XOR B = (A И NOT B) ИЛИ (НЕ A И B).

и что большинство обычных инструментов обработки изображений имеют и, или, а не операции, все остальное довольно просто:)

Работая с Python, вы можете просто выполнить script операцию и даже добавить ее в качестве плагина в gimp;)

Ответ 5

Если вы хотите сделать это самостоятельно, сделайте это по пикселям. Если вам нужна библиотека, я рекомендую OpenCV. Это очень хорошая библиотека с открытым исходным кодом с огромными операциями, поддерживаемыми в области обработки изображений. Он поддерживает прямой XOR с помощью оператора ^. Удачи.