it-swarm.com.ru

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

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

Это должно привести к тому же окончательному изображению, что и в режиме смешивания 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 для изображений.

Кто-нибудь знает способ сделать это?

15
Qqwy

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 над изображением". В приведенном выше выражении u и v обозначают первое и второе входные изображения соответственно.

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

    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

Вуаля!

20
mathematical.coffee

Я обнаружил потребность в 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

enter image description here

10
RobLabs

Вот как я бы сделал в 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"));
5
Martijn Courteaux

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

2
Pervez Alam

Знаю это

A XOR B = (A И НЕ B) OR (НЕ A И B).

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

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

1
jlengrand

OpenCV имеет все логические операторы на изображениях и пустых изображениях, используя bitwise_ # Где # может быть xor, и, и, не ... См. OpenCV - Пересечение между двумя двоичными изображениями

0
user1270710