LoginSignup
47
40

More than 1 year has passed since last update.

ImageMagick で画像比較 (Compare)

Last updated at Posted at 2018-06-16

ImageMagick は compare コマンドで2つの画像を比較して差分ハイライト画像を生成したり、その差分をメトリックに応じて数値化する事ができます。

画像サンプル

ツイッターで画像の再投稿が繰り返される事による画質劣化で、おそらく日本で一番有名な「5000兆円欲しい!」画像を実験サンプルに使わせて頂きます。

Original JPEG quality:50 JPEG quality:10
5000.png 5000-q50.jpg 5000-q10.jpg
5000.png 5000-q50.jpg 5000-q10.jpg
5000-crop200.png 5000-q50-crop200.png 5000-q10-crop200.png
5000-crop200.png 5000-q50-crop200.png 5000-q10-crop200.png
% convert 5000.png -quality 50  5000-q50.jpg
% convert 5000.png -quality 10  5000-q10.jpg
% convert 5000.png     -crop 200x200+0+0  5000-crop200.png
% convert 5000-q50.jpg -crop 200x200+0+0  5000-q50-crop200.png
% convert 5000-q10.jpg -crop 200x200+0+0  5000-q10-crop200.png

compare コマンド

ハイライト画像について

比較したい2枚の画像を指定して、ハイライト画像を生成します。

compare 5000.png 5000-q50.jpg  5000-q50-diff.png
compare 5000.png 5000-q10.jpg  5000-q10-diff.png
compare 5000-crop200.png 5000-q50-crop200.png  5000-q50-crop200-diff.png
compare 5000-crop200.png 5000-q10-crop200.png  5000-q10-crop200-diff.png

色に違いのない場所は白。少しでも変化があれば赤で、違いが大きいほど濃い赤でハイライトします。

JPEG quality:50 JPEG quality:10
5000-q50-diff.png 5000-q10-diff.png
5000-q50-diff.png 5000-q10-diff.png
5000-q50-crop200-diff.png 5000-q10-crop200-diff.png
5000-q50-crop200-diff.png 5000-q10-crop200-diff.png

ハイライト色指定

ハイライト色を変更出来ます。赤が苦手な人向けに良いでしょう。但し色は階調なしで違いがあるか無いかの2色になります。残念。

% compare 5000.png 5000-q50.jpg -highlight-color SeaGreen  5000-q50-diff-SeaGreen.png
% compare 5000.png 5000-q50.jpg -highlight-color SeaGreen -lowlight-color PaleGreen  5000-q50-diff-SeaGreenPaleGreen.png
$ compare 5000-crop200.png 5000-q50-crop200.png -highlight-color SeaGreen  5000-q50-crop200-diff-SeaGreen.png
$ compare 5000-crop200.png 5000-q50-crop200.png -highlight-color SeaGreen -lowlight-color PaleGreen  5000-q50-crop200-diff-SeaGreenPaleGreen.png
SeaGreen SeaGreen - PaleGreen
5000-q50-diff-SeaGreen.png 5000-q50-diff-SeaGreenPaleGreen.png
5000-q50-crop200-diff-SeaGreen.png 5000-q50-crop200-diff-SeaGreenPaleGreen.png

グレースケール

比較画像のファイル形式がグレースケールの場合、ハイライト画像もグレースケールです。

% convert 5000.png -type grayscale -define png:color-type=0  5000-gray.png
% convert 5000-q50.jpg -type grayscale -define png:color-type=0  5000-q50-gray.png
% convert 5000-q10.jpg -type grayscale -define png:color-type=0  5000-q10-gray.png
% compare 5000-gray.png 5000-q50-gray.png  5000-q50-gray-diff.png
% compare 5000-gray.png 5000-q10-gray.png  5000-q10-gray-diff.png

なお、グレースケールの色しか使っていなくても、ファイル形式が RGB だった場合は、赤くハイライトします。コマンド引数でいうと -define png:color-type=0 が大事です。

5000-q50-gray-diff.png 5000-q10-gray-diff.png
5000-q50-gray-diff.png 5000-q10-gray-diff.png

ちょっと分かりにくいですけど、グレースケールで閉じて処理できる点で合理的な挙動です。

fuzz

デフォルトだと色の値が 1 違うだけでハイライトしてしまいます。見た目で分からない部分を無視したい場合は、-fuzz で削る事ができます。

% compare -fuzz  5% 5000-crop200.png 5000-q50-crop200.png  5000-q50-crop200-fuzz5-diff.png
% compare -fuzz  5% 5000-crop200.png 5000-q10-crop200.png  5000-q10-crop200-fuzz5-diff.png
% compare -fuzz 10% 5000-crop200.png 5000-q50-crop200.png  5000-q50-crop200-fuzz10-diff.png
% compare -fuzz 10% 5000-crop200.png 5000-q10-crop200.png  5000-q10-crop200-fuzz10-diff.png
% compare -fuzz 30% 5000-crop200.png 5000-q50-crop200.png  5000-q50-crop200-fuzz30-diff.png
% compare -fuzz 30% 5000-crop200.png 5000-q10-crop200.png  5000-q10-crop200-fuzz30-diff.png
q:50 fuzz5 q:10 fuzz:5
5000-q50-crop200-fuzz5-diff.png 5000-q10-crop200-fuzz5-diff.png
q:50 fuzz10 q:10 fuzz:10
5000-q50-crop200-fuzz10-diff.png 5000-q10-crop200-fuzz10-diff.png
q:50 fuzz30 q:10 fuzz:30
5000-q50-crop200-fuzz30-diff.png 5000-q10-crop200-fuzz30-diff.png

この例では -fuzz 5 の時にブロックノイズがよく分かりますね。

metric

何かしら観測した値の変化を調べる際には差分を数値化するものですが、対象によって差分の計算方法は様々です。その計算に用いる距離関数をメトリックと呼びます。

ちなみに、-metric 指定した時は、(stdout でなく) stderr に数値が出力されます。仕様です。

標準出力に出す他のデータと区別したいそうですが、正直、これは微妙ですね。^^;

(閑話休題)

compare の -metric オプションは、見た目の差分を定量化する様々なメトリックに対応しています。

% compare -list Metric
AE
DSSIM
Fuzz
MAE
MEPP
MSE
NCC
PAE
PHASH
PSNR
RMSE
SSIM

このうち、PSNR と SSIM が特に有名です。
こちらで少し紹介しているので参考までに。

各々の、計算結果を表示してみます。

% for m in `compare -list Metric` ;
    do echo "\n" $m ;
      compare -metric $m 5000.png 5000-q50.jpg  NULL: ;
    done
 AE
253997
 DSSIM
0.16212
 Fuzz
2807.22 (0.0428354)
 MAE
1026.85 (0.0156687)
 MEPP
1.86687e+09 (0.00244649, 1)
 MSE
120.248 (0.00183487)
 NCC
0.858571
 PAE
65535 (1)
 PHASH
386.076
 PSNR
27.3639
 RMSE
2807.22 (0.0428354)
 SSIM
0.67576%

なお、今まで通り 3つ目にファイル名を指定すると差分をハイライトした画像を生成しますが、メトリック指定での違いがないので NULL: で捨ててます。 (みた感じ PSNR に似てるけど少し違ってて、決め打ちでの独自処理っぽい)

画像

compare を単純に使うと赤いハイライトになりますが、R,G,B の3チャネルに分解して処理すると、RGB 別の差分が見られます。

% convert 5000.png     -channel R,G,B -separate  5000-RGB.png
% for q in 50 10
    do convert 5000-q$q.jpg -channel R,G,B -separate  5000-q$q-RGB.png
    for i in 0 1 2
      do compare 5000-RGB-$i.png 5000-q$q-RGB-$i.png 5000-q$q-RGB-$i-diff.png
    done
    convert 5000-q$q-RGB-?-diff.png -combine -set colorspace sRGB 5000-q$q-RGB-diff.png
  done
Red Green Blue
5000-RGB-0.png 5000-RGB-1.png 5000-RGB-2.png
5000-RGB-0.png 5000-RGB-1.png 5000-RGB-2.png
[5000-q50-RGB-0.png [5000-q50-RGB-1.png [5000-q50-RGB-2.png
5000-q50-RGB-0.png 5000-q50-RGB-1.png 5000-q50-RGB-2.png
[5000-q10-RGB-0.png [5000-q10-RGB-1.png [5000-q10-RGB-2.png
5000-q10-RGB-0.png 5000-q10-RGB-1.png 5000-q10-RGB-2.png
Red Green Blue
5000-q50-RGB-0-diff.png 5000-q50-RGB-1-diff.png 5000-q50-RGB-2-diff.png
5000-q50-RGB-0-diff.png 5000-q50-RGB-1-diff.png 5000-q50-RGB-2-diff.png
5000-q10-RGB-0-diff.png 5000-q10-RGB-1-diff.png 5000-q10-RGB-2-diff.png
5000-q10-RGB-0-diff.png 5000-q10-RGB-1-diff.png 5000-q10-RGB-2-diff.png
5000-q50-RGB-diff.png 5000-q10-RGB-diff.png
5000-q50-RGB-diff.png 5000-q10-RGB-diff.png

composite -compose difference

先程のハイライト表示では、間違い探しといった用途には便利です。
一方、色の差分をそのまま画像にすれば、どの程度色が違うのかの度合いまで分かります。
ただし、単純な R,G,B 値の差なので見た目の違いの正確さには眼をつむります。
(おそらく、Lab に変換してから差分をとった方が良さそう)

$ composite 5000.png 5000-q50.jpg -compose difference  5000-q50-diff.png
5000-q50-diff.png
5000-q50-diff.png

差分が小さく差分画像が暗くてよく見えない時には、-auto-level が便利です。
このオプションは一番暗いピクセルと一番明るいピクセルを 0 と 255 にして、全体の明るさをその間で引き伸ばします。

% convert 5000-q50-diff.png -auto-level  5000-q50-autolevel-diff.png
% 
5000-q50-autolevel-diff.png
5000-q50-autolevel-diff.png

はい。変わりません。。。何故ならば、左上2pixelに大きな差分があるからで。。左上を拡大してみます。

% convert 5000-q50-diff.png -crop 32x32+0+0  32x32.png
$ convert 32x32.png -sample 800% -fx "(i%8>0)*(j%8>0)*u"  32x32-dot.png
32x32.png 32x32-dot.png
32x32.png 32x32-dot.png

draw 等を使って黒で塗りつぶすと、期待通りになります。

(追記) -auto-level でなく -normalize を使うと大丈夫かもしれません 参考) https://qiita.com/yoya/items/1da8e8e04881bab67015#-normalize

$ convert 5000-q50-diff.png -fill black -draw "line 0,0 1,0" -auto-level  5000-q50-draw-al-diff.png
5000-q50-draw-al-diff.png
5000-q50-draw-al-diff.png

青の値が大きいので、全体的に明るくなりきれないのは、-auto-level の限界です。

PSNR 値の不具合 (2016年7月〜2017年2月、〜2018年9月)

同一画像を比較した際の PSNR 値は inf(無限大)のはずですが、2016年〜2017年(6系は〜2018年)の期間は 0 を返す不具合がありました。古い ImageMagick を使っている場合に注意が必要です。

ChangeLog 上の話

ChangeLog 上では ImageMagick-6.9.5-4, (2016年7月30日リリース) で不具合が入り、ImageMagick-6.9.8-0, (2017年3月12日リリース) で修正された事になってます。7系同時リリースは 7.0.2-5 と 7.0.5-2 が該当します。

実際に試すとだいぶバージョンが違うので要注意です。

実際の話

以下、バージョンの右のカッコは(リリース日付)です。

  • ImageMagick-7 系

不具合が存在するのは ImageMagick-7.0.2-6(2016/7/30) から 7.0.5-0(2017/2/21) まで。
大丈夫なのは 7.0.5-1(2017/3/5) 以降。

% ~/ImageMagick/7.0.2-4/bin/compare -metric PSNR rose: rose: NULL:  # あれれ、まだ正しい?
inf
% ~/ImageMagick/7.0.2-5/bin/compare -metric PSNR rose: rose: NULL:  # あれれれ?
inf
% ~/ImageMagick/7.0.2-6/bin/compare -metric PSNR rose: rose: NULL:  #不具合が入った
0
()
% ~/ImageMagick/7.0.5-0/bin/compare -metric PSNR rose: rose: NULL:
0
% ~/ImageMagick/7.0.5-1/bin/compare -metric PSNR rose: rose: NULL:  # やっと治った。
inf
  • ImageMagick-6 系

不具合が存在するのは ImageMagick-6.9.5-4 (2016/7/30) から 6.9.10-12(2018/9/23) まで、
大丈夫なのは 6.9.10-13(2018/10/22)以降。

% ~/ImageMagick/6.9.5-3/bin/compare -metric PSNR rose: rose: NULL:
inf
% ~/ImageMagick/6.9.5-4/bin/compare -metric PSNR rose: rose: NULL:  #不具合が入った
0
% ~/ImageMagick/6.9.7-10/bin/compare -metric PSNR rose: rose: NULL:
0
% ~/ImageMagick/6.9.8-0/bin/compare -metric PSNR rose: rose: NULL:  # あれれ、治ってない?
0
()
% ~/ImageMagick/6.9.10-12/bin/compare -metric PSNR rose: rose: NULL:
0
% ~/ImageMagick/6.9.10-13/bin/compare -metric PSNR rose: rose: NULL:  # やっと治った。
inf

7系から 6系へのバックポートが年単位で遅れてます。

TODO (物足りない要素)

  • 画像サイズが違う場合
  • RGB 以外では?
  • 各メトリックの紹介
  • 対応するソースコードの説明 (GetImageDistortions とか)

参考URL

47
40
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
40