コマンドラインで2つの画像の Bitwise XOR を取得する方法を探しています(またはプログラムやスクリプトで実装できる別の方法で)。
これにより、それをサポートする画像エディター(Paint.NET、Photoshopなど)でXORブレンディングモードを使用した場合と同じ最終画像が得られます)
例として、私が持っているとしましょう画像A:
および画像B:
その場合、結果は次のようになります。
もちろん、これの楽しい部分は、画像Cと画像Bを再びXORすると、画像Aの正確なコピーが得られることです。
今、私はこれをプログラムで行う方法をインターネット全体で探していましたが、何も見つかりませんでした。 ImageMagickでさえ、画像に対してビット単位のXORを実行することをサポートしていません。
誰かがこれを行う方法を知っていますか?
ImageMagickはそれを行うことができますが、少し複雑です。 1つの方法は次のとおりです。
convert img1 img2 -fx "(((255*u)&(255*(1-v)))|((255*(1-u))&(255*v)))/255" img_out
(img1
、img2
、img_out
は、それぞれ2つの入力ファイル名と1つの出力ファイル名です)。
それは少し醜いです(私よりも多くのImageMagick-fuを持っている人がそれをクリーンアップできると確信していますが、それは次のように機能します:
-fx "xxx"
は基本的に「画像に対して操作xxx
を実行する」と言っています。上記の式で、u
とv
は、それぞれ1番目と2番目の入力画像を表します。
現在、-fx
はビット単位のAND&
とビット単位の演算子の方法でビット単位のOR |
のみを持っています。ビット単位のXORを再構築するには、
convert img1 img2 -fx "(u & NOT v) | (NOT u & v)" img_out
NOT
(論理的なNOT
はありますが、ビット単位のNOT
はありません)を取得するには、NOT x = 255-x
ifx
は8ビットです。したがって、NOT u
を取得するには、画像u
が8ビットであると仮定して、255-u
を実行できます。したがって、ImageMagickコマンドは次のようになります。
convert img1.png img2.img -fx "((255-u)&v)|(u&(255-v))" image_xor.png
ここでの1つの問題は、ImageMagickがfx
を実行すると、[0,1]
ではなく[0,255]
の範囲のu
とv
のすべてのピクセルが正規化されることです。私たちは期待しており、整数以外のネジをビット単位で実行すると、問題が発生します。
したがって、上記の式のu
とv
のallオカレンスに255を掛けて(ビット演算が機能するように)、除算する必要があります。 ImageMagickが期待する範囲[0,1]
に戻るために、最後に255まで。
これにより、元のコマンドが得られます。
convert img1 img2 -fx "(((255*u)&(255*(1-v)))|((255*(1-u))&(255*v)))/255" img_out
出来上がり!
画像に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
これが私がJavaで行う方法です:
2つの画像のすべてのピクセルを一度に繰り返します。 (forループ(y)内のforループ(x))。もちろん、BufferedImage
を使用してください。次の手順でピクセルの色を取得できます。
int color = img.getRGB(x, y);
他の画像についても同じことを行い、2つの色に対してxor演算を実行します。結果の値を、2つの入力画像と同じサイズの新しい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"));
自分でやりたい場合は、ピクセルごとに行います。ライブラリが必要な場合は、OpenCV
をお勧めします。これは非常に素晴らしく、画像処理領域でサポートされている巨大な操作を備えたオープンソースライブラリです。 ^
演算子を使用した直接[〜#〜] xor [〜#〜]をサポートします。幸運を。
知っています
A XOR B =(A AND NOT B)OR(NOT A AND B)。
そして、一般的な画像処理ツールのほとんどには、操作があり、操作がないので、残りは非常に簡単です:)
Pythonで作業すると、操作を実行し、それをプラグインとしてgimpに追加する簡単なスクリプトを作成できます;)
OpenCVには、bitwise_#を使用した画像とnumpy画像のすべての論理演算子があります。ここで#はxor、and、およびではなく...を参照してください。 OpenCV-2つのバイナリ画像間の交差