Processing3.3 + OpenCV 3.2.0 環境構築&テンプレートマッチング(Mac)

Processing3.3 + OpenCV 3.2.0 環境構築&テンプレートマッチング(Mac)

久しぶりにProcessingとOpenCVで試してみたので,メモ.
 
 
1. Processingのインストール
Processingサイトから環境に合った最新版をダウンロード.
Processingはダウンロードしたファイルを解凍するだけで,そのまま使えます.
 
 
2. ProcessingにOpenCVライブラリを追加
メニューの「スケッチ」→「ライブラリを追加」からContribution Managerを起動.
LibrariesでOpenCVを選択し,Installする.


 
これで,OpenCVがProcessingで使えるようになります.
しかし,何故か,テンプレートマッチングのコードを動かしたところ,
No library found for org.opencv.core.Core
というエラーが出て止まってしまいます.
結局,OpenCVサイトからOpenCV3.2.0をダウンロードして,インストールしてみることに.
 

3.OpenCVのインストール
2でダウンロードしたzipファイルを展開.適当な場所へコピーします.

HomeBrewが入っていない場合はインストールしておきます.
ターミナルで,

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

このスクリプトを実行すればいいだけですが,変わっている可能性もあるので,最新版はサイトでチェックしてください.
 
HomeBrewがインストールできたら,そのままターミナルで,以下のコマンドを入力.

brew tap homebrew/science
brew install opencv3 --with-java

これで,OpenCVがProcessingで使えるようになります.

eclipseなどで使いたい場合は,まだ更に設定が必要ですが,それはまた別の記事で.
 
 
4. テンプレートマッチング
コードは,ほぼコチラを参考にさせていただきました.

import gab.opencv.*;
import org.opencv.core.Mat;
import org.opencv.core.CvType;
import org.opencv.imgproc.Imgproc;
import org.opencv.core.Core.MinMaxLocResult;
import org.opencv.core.Core;

// 入力画像の準備
PImage inputImage = loadImage("temp.png", "png");
OpenCV inputCV = new OpenCV(this, inputImage);
Mat inputMat = OpenCV.imitate(inputCV.getGray());

// テンプレート画像の準備
PImage templateImage = loadImage("temp2.jpg", "jpg");
OpenCV templateCV = new OpenCV(this, templateImage);
Mat templateMat = OpenCV.imitate(templateCV.getGray());

// 結果格納用の行列の準備
int resultCols = inputMat.cols() - templateMat.cols() + 1;
int resultRows = inputMat.rows() - templateMat.rows() + 1;
Mat resultMat = new Mat(resultRows, resultCols, CvType.CV_32FC1);

// テンプレートマッチングを実行
Imgproc.matchTemplate(inputCV.getColor(), templateCV.getColor(), resultMat, Imgproc.TM_CCOEFF_NORMED);

// 結果を描画
size(640, 480);
image(inputImage, 100, 0);
image(templateImage, 10, 10);


MinMaxLocResult mmlr = Core.minMaxLoc(resultMat);

if (mmlr.maxVal > 0.9) {
  println("Val: " + mmlr.maxVal);
  stroke(255, 0, 0);
  strokeWeight(3);
  noFill();
  rect((int)mmlr.maxLoc.x + 100, (int)mmlr.maxLoc.y, templateMat.cols(), templateMat.rows());
}

 
実行結果
左の画像とマッチしている部分が赤枠で囲まれます.

 
問題点
テンプレートマッチングは比較的簡単にできますが,比較する画像同士の大きさや解像度,向き,写真の場合は光の当たり具合による色の変化に大きく依存します.
つまり,元画像から直接切り出した画像を用いて,それが元画像のどの部分かを探すことはできますが,似ている画像や少し変化をつけた画像から探し出すのはほぼできません.
そういったことがしたい場合,特徴点検出(SIFTやSURFなど)を使うか,機械学習が必要になりそうです.