結論
- ImageMagick の
compare
コマンドで, Perceptual Hash (pHash) により同一構図かチェックする. - ImageMagick の
convert
とidentify
コマンドで, Canny 法によりエッジ検出し同一構図の n 枚から最も鮮明な 1 枚を残す. - ソースはここに置いた: GitHub - typewriter/unblurred-photo-picker
背景
手ブレしたくないが, ISO 感度もあまり上げたくない(綺麗に撮りたい).その場合,ギリギリのシャッタースピードで何枚も撮る,ということをよくやります.しかし,撮影後の写真の選別が極めて面倒なうえ,かなり機械的な作業です.
機械的な作業… ということは機械で出来るのではないでしょうか.やってみました.
同一構図の判定
同一構図の判定は,画像の類似度が高いかどうかで行うこととします.ただし,画像処理はさっぱり分からないため, ImageMagick に全力で甘えます.
ImageMagick には compare
コマンドがあり,お手軽に画像比較を行うことが可能です.
画像比較に使用できるメトリクスの一覧は ImageMagick - Command-line Options#-metric type にありますが,今回は PHASH (Perceptual Hash) を用います.
# ImageMagick 7 系.小さいほど類似度が高い. $ magick compare -metric PHASH P9240031.JPG P9240035.JPG NULL: 13.7601
Perceptual Hash ではハミング距離を取って類似度とする例を見かけましたが, ImageMagick の数値はそうではないようです.まあ気にせずいくつかの画像で試してみます.
画像1 | 画像2 | 備考 | 出力値 |
---|---|---|---|
同じ構図 | 0.501766 | ||
少し下に向けた | 8.26181 | ||
別構図 | 39.5355 |
同一構図では数値が小さく,異なる構図では数値が大きくなりました.使えそうです.
「最も鮮明な」写真の判定
やはり画像処理はさっぱり分からないため,こちらも ImageMagick に頼ります.
当初は「標準偏差 (Standard deviation) が大きければ値のバラつきが大きい→鮮明」と考えていましたが,手ブレした写真のほうが標準偏差が高いケースが複数枚でみられたため不採用です.
$ magick identify -format "{ \"Kurtosis\": %[kurtosis], \"StandardDeviation\": %[standard-deviation], \"Skewness\": %[skewness], \"Entropy\": %[entropy] }" 20171104_PB040552.JPG { "Kurtosis": 3.04856, "StandardDeviation": 11783.4, "Skewness": 1.91352, "Entropy": 0.760502 }
画像(切り抜き) | 標準偏差 |
---|---|
11783.4 | |
11899.3 |
代わりに, Canny Edge Detection でエッジ検出した結果の標準偏差を用いることにします.
$ magick convert 20171104_PB040552.JPG -canny 0x1+10%+30% edge.png $ magick identify -format "{ \"Kurtosis\": %[kurtosis], \"StandardDeviation\": %[standard-deviation], \"Skewness\": %[skewness], \"Entropy\": %[entropy] }" edge.png { "Kurtosis": 13.5456, "StandardDeviation": 14823.4, "Skewness": 3.94279, "Entropy": 0.303514 }
画像(切り抜き) | エッジ検出後(同左) | 標準偏差 |
---|---|---|
14823.4 | ||
11678.3 |
良さげな感じになりました.
スクリプト
Rubyで書きました。裏でImageMagickのコマンドガンガン実行します。
参考
*1:バックアップも兼ねているのでアップロードはしている