Поиск способа выполнения Побитового 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 с помощью оператора ^
.
Удачи.
Ответ 6
OpenCV имеет все логические операторы на изображениях и numpy-изображениях с использованием bitwise_ # Где # может быть xor, а, и, а не... См. OpenCV - Пересечение двух двоичных изображений