rmagick(ImageMagick)を使って画像の差分を取得する
画像差分が取りたい
修正前、修正後の結果を画像比較できるとテストの安心感が高まりそうという気持ちから、rmagickの機能を調べてみました。
参考にしたもの
- Webページを監視して表示崩れが起きていないか検出できるE2Eテストを実装しました
- https://github.com/rmagick/rmagick
- http://www.rubydoc.info/gems/rmagick/
確認環境
- ruby 2.2.3
- rmagick 2.15.4
rmagickのインストール方法
Githubのwikiを参照下さい。
画像取得について
Seleniumで画像キャプチャを取ることを想定していますが、今回は画像取得については触れずに別で書こうと思います
画像の差分を取る
rmagickで画像を読み込む
まずはrmagickで画像を読み込むところから。
require 'rmagick' img = Magick::Image.read('./sample.jpg').first
Magick::Image.read
の結果が配列で返ってきますので、first
としています。
画像がどのくらい違うか確認する:Magick::Image#difference
Magick::Image#difference
というメソッドがあるので、これを使うと同じ画像かどうかが分かるようです。リファレンスの説明にはCall the IsImagesEqual function.
という記述がありました。
使ってみる
require 'rmagick' img = Magick::Image.read('./sample.jpg').first p img.difference(img) # => [0.0, 0.0, 0.0]
同じだと0で返ってくるようです。
返ってくる値は何なのか
リファレンスを見ると
mean_error_per_pixel,normalized_mean_error,normalized_maximum_error
の3つの値だと書いてありました。
画像系に詳しい人だともしかしたらこれで分かるのかもしれませんが、私にはよく分からず。
ImageMagick側を見れば分かるかな、ということでImageMagickをキーワードにググってみたところ、このページを発見。
曰く、
mean_error_per_pixel: This value is the mean error for any single pixel in the image. normalized_mean_error: This value is the normalized mean quantization error for any single pixel in the image. This distance measure is normalized to a range between 0 and 1. It is independent of the range of red, green, and blue values in the image. normalized_maximum_error: Thsi value is the normalized maximum quantization error for any single pixel in the image. This distance measure is normalized to a range between 0 and 1. It is independent of the range of red, green, and blue values in your image.
ということみたいです。
違いがあるかないかという点では0であるかを見れば良さそうで、どのくらい違うかはこの値を見て判断することが出来そう(出来そうだけどどうやったら出来るかはいまいち分からない)
実際どんな感じになるのか
適当な画像を用意して比較してみました
全く同じファイル
上述の通り [0.0, 0.0, 0.0]
同じファイルをサイズを変えて比較してみる
- 640×480のGIFファイルを用意して320×240にサイズ変更したものと比較すると
[521.8944702148438, 0.0070885103517538675, 1.0]
ファイルの内容をちょっと変えてみる
- 元々のファイルに「テスト」みたいな文字を加えたものと比較すると
[37.7886962890625, 0.0004698213267336715, 1.0]
- 「テスト」の文字をとても小さくすると
[5.609326362609863, 5.188514493355332e-05, 0.9294117647058824]
- 「テスト」の文字をとても大きくすると
[5286.41259765625, 0.07936659467536895, 1.0]
- 背景色の色味をちょっと変えてみる
[8371.1787109375, 0.021862748084959475, 0.17254901960784313]
- 背景色の色味を強めに変えてみる
[30593.5625, 0.29990951254957343, 0.6313725490196078]
とりあえずの結論
はっきりは分からないのと、テストデータも手元のツールで簡単に使っただけなので、正確性があるかないが大変に怪しいですが、左端の値が一番感覚と近いかなぁという印象(違いが小さいと値も小さい)。本当は閾値みたいに使えたらと思ったのですが、ちゃんと使うには、今のところ値の意味を理解できていないがために難しそうです。もちろん、閾値ではなくて、「0じゃなかったら違う画像!」みたいには使えると思います。
差分を画像として確認する:Magick::Image#composite または Magick::Image#composite!
実際に、DIFFの結果が見たい、という場合にはMagick::Image#composite
またはMagick::Image#composite!
が使えます。DIFFを意識した重ね合わせができて、同じところは黒くなるので、黒くないところが違うところ、という形で確認できます。
使ってみる
require 'rmagick' img_a = Magick::Image.read('./sample-a.jpg').first img_b = Magick::Image.read('./sample-b.jpg').first img_a.composite(img_b,Magick::NorthWestGravity,Magick::DifferenceCompositeOp).write('./image_diff.jpg')
compositeメソッドについて
最初の引数は、合成する画像データです
2つ目の引数は、画像を合成する位置の指定です。
0,0
とかでも良いですし、左上からであればMagick::NorthWestGravity
、中央からであればMagick::CenterGravity
のようにモジュール内に定義してある定数を使うこともできるようです3つ目の引数は、重ね方の指定です。
Magick::DifferenceCompositeOp
の指定をすると、同じところが黒くなって重なります。DIFFでなければ、別の値を指定して画像の合成ができるようです
ruby gem を作りました
インタフェースデザインの心理学 ―ウェブやアプリに新たな視点をもたらす100の指針
- 作者: Susan Weinschenk,武舎広幸,武舎るみ,阿部和也
- 出版社/メーカー: オライリージャパン
- 発売日: 2012/07/14
- メディア: 大型本
- 購入: 36人 クリック: 751回
- この商品を含むブログ (28件) を見る
- 作者: Dima Kovalenko,玉川紘子,太田健一郎,笹井崇司
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/09/18
- メディア: 大型本
- この商品を含むブログ (3件) を見る