概要
node-opencvを用いたテンプレートマッチングの実践録。
あまり実装例がなかったので、試行錯誤した結果を載せてみます。
ソースはこちら。
docker-composeを用いての環境構築とテンプレートマッチングを行うアプリケーション入りです。
テンプレートマッチングとは
テンプレートマッチングとは、探索対象の画像内からテンプレート画像が出現する座標を探索するものです。
例えば指定の画像内に指定のアイコンが存在するかなどを探すことができます。
実装
環境
環境は https://hub.docker.com/r/siomiz/node-opencv/ を利用して、構築しています。
ほぼそのままです。
実装
以下がコードです。今回は複数のテンプレートを探索して、各テンプレートにマッチしてる座標があるかどうか(探索画像内にテンプレートが現れるか)を見ています。
cv.readImage(BASE_IMAGE_PATH, function(err, baseImage) {
if (err) return console.error('error loading image');
baseImage.convertGrayscale()
var results = []
for (var searchImagePath of searchImagePaths) {
// 検出対象画像を読み込み、マッチングを行う
cv.readImage(searchImagePath, function(err, searchImage) {
if (err) return console.error('error loading image');
searchImage.convertGrayscale()
let output = baseImage.matchTemplateByMatrix(searchImage, 3);
let matches = output.templateMatches(0.99, 1.0, 5, false)
console.log(matches)
if (matches.length > 0 && typeof(matches[0]) != 'undefined') {
console.log('match!')
results.push(true)
} else {
console.log('unmatch!')
results.push(false)
}
})
}
console.log(results)
})
苦慮したところがいくつかあるのであげておきます。
背景色
baseImage.convertGrayscale()
これは文字どおりグレースケールに変換する関数なのですが、これはテンプレート画像の背景色と探索画像の背景色が違う場合にもマッチングが取れるように行なっています。
もし、その場合はマッチングと判定しない場合は不要かもしれません。
また、グレースケールに変換するため画像はjpgで用意しました。
matchTemplate
let output = baseImage.matchTemplateByMatrix(searchImage, 3);
let matches = output.templateMatches(0.99, 1.0, 5, false)
matchTemplate
という関数もあるのですが、なかなかうまくいかず・・・。
matchTemplateByMatrix
を利用して、opencv内で画像データ保持に用いられるMatrixオブジェクトとして吐き出してから、マッチング結果を検出する templateMatches
関数を実行するとうまくいきました。
ちなみに templateMatches
関数の第一引数、第二引数はどれくらいの割合の類似が見られた場合にマッチングしたとみなすかの下限・上限の設定になっています。
今回の例だと 99%~100%をマッチングとみなすようになっていますが、この値はどの程度の精度を求めるかによって調整していく必要があります。
templateMatches
の結果は以下のように返ってきます。
指定の割合範囲のマッチングが見られた座標と確からしさ(probability)がオブジェクトとして、配列に入って返却されます。
返却される要素数は第三引数によります。また、マッチングがない場合は空の要素が返却されます。
以下は1座標のみマッチングが検出された際の例です。
[ { x: 4, y: 159, probability: 0.9926717877388 }, , , , ]
まとめ
node-opencvでテンプレートマッチングを試してみた事例でした。
個人的には慣れているのでNode.jsを今回選択したのですが、情報量にだいぶ差があるようなので余程の事情がなければ情報量が多そうなPythonやC++を利用することをお勧めします・・・w
OpenCV自体は初めて触りましたが、これ以外でも様々機能があり画像処理には重要な技術だと実感したので、今後もいろいろ試してみようと思います。