1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

テンプレートマッチングを使って複数検出する[C++][OpenCV]

Posted at

#はじめに
cv::matchTemplate()のサンプルコードとして

C++
cv::matchTemplate(search_img, tmp_img, result_img, cv::TM_CCOEFF_NORMED);
cv::Point max_pt;
double maxVal;
cv::minMaxLoc(result_img, NULL, &maxVal, NULL, &max_pt);

がありますが、cv::minMaxLoc()は最大値を求めるので1箇所しか検出することができません。
1つの画像から複数箇所を検出したい場合、Pythonではnp.where()などがありますが、C++にはないので自分で実装する必要があります。

Googleで[ opencv テンプレートマッチング 複数 c++ ]と検索すると
OpenCV のテンプレートマッチを使って駒を検出
[[OpenCV][C++]テンプレートマッチングを使って複数検出してみた]
(https://qiita.com/satsukiya/items/c8828f48be7673007007
"[OpenCV][C++]テンプレートマッチングを使って複数検出してみた")
これらの記事がよく見られていますが、自分で書いたコードが違う感じになったので
記事に残しておこうと思います。

#使用するデータ
チュートリアルではマリオが使われているのでそれに習って画像を用意しました
Screenshot from 2021-07-12 09-29-10.png

テンプレート画像
Screenshot from 2021-07-12 09-29-10-coin.png

#サンプルコード

find_multi_template.cpp
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

#define THRESHOLD 0.7
#define FIND_TARGET_NUM 30

int main(int argc, char** argv){
  //元画像と検出画像の追加
  cv::Mat src = cv::imread("../picture/src.png", 1);
  cv::Mat tmp = cv::imread("../picture/template.png", 1);

  //マッチング結果の画像と出力用画像の宣言
  cv::Mat result, dist;
  src.copyTo(dist);
  //テンプレートマッチングの実行
  cv::matchTemplate(src, tmp, result, cv::TM_CCOEFF_NORMED);

  //最大値を持つ画素の検索
  double val;
  cv::Point loc;
  cv::minMaxLoc(result,NULL,&val,NULL,&loc);

  for(int i=0;i<FIND_TARGET_NUM && fabs(val) > THRESHOLD; ++i){

    //検出部分のマスク
    cv::rectangle(result, cv::Point(loc.x-tmp.cols/2,loc.y-tmp.rows/2), cv::Point(loc.x+tmp.cols/2, loc.y+tmp.rows/2), cv::Scalar(0), -1);
    //出力用画像への描画
    cv::rectangle(dist, cv::Point(loc.x,loc.y), cv::Point(loc.x+tmp.cols, loc.y+tmp.rows), cv::Scalar(0,0,255), 2);
    //再度最大値を持つ画素の検索
    cv::minMaxLoc(result,NULL,&val,NULL,&loc);
  }

  //結果画像の出力
  cv::imwrite("../picture/output.png", dist);

  return 0;
}

#結果
出力画像は以下のようになります。
output.png

#まとめ
今回使用したコードは以下のリポジトリにおいておくのでご自由に使用してください
pictureディレクトリの画像を変更すれば汎用的に使用できます
find_multi_template

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?