Python
 Computer >> コンピューター >  >> プログラミング >> Python

PythonとOpenCVで実現するテンプレートマッチングの基本とマルチスケール対応

テンプレートマッチングとは、実際の画像の中から、あらかじめ用意した小さな画像(テンプレート)と一致する部分を探し出す技術です。基本的にはパターンマッチングの一種であり、物体検出や顔認識など、さまざまなコンピュータビジョンのタスクの基礎となる手法です。

PythonではOpenCVモジュールを使うことで、このマッチング処理を簡単に実装できます。本記事では、OpenCVのテンプレートマッチング機能を使った具体的な方法を解説します。

OpenCVのインストール

OpenCVの機能を利用するには、まずpipでライブラリをインストールします。

sudo pip3 install opencv-python

閾値(スレッショルド)の重要性

テンプレートマッチングには「どの程度一致していれば検出とみなすか」を決める精度係数、いわゆる閾値(threshold)が存在します。

例えば、目や顔のパーツの画像をテンプレートとして渡せば、顔認識的な仕組みを作ることも可能です。しかし、人の目は一人ひとり形が異なるため、精度レベルを100%に設定するとほとんど何も検出できません。逆に50%程度に緩めると、より多くの候補を検出できます。一般的には、80%前後の精度レベルが多くの場面で使われています。

テンプレートマッチングの手順

  • 元画像を読み込み、グレースケール画像に変換する。

  • テンプレートもグレースケール画像として読み込む。

  • テンプレートを元画像上でスライドさせながら、一致度が高い位置を探す。

  • 結果が設定した閾値以上であれば、その位置を検出箇所としてマークする。

基本的なサンプルコード

まず、以下の元画像とテンプレート画像を用意します。

元画像

PythonとOpenCVで実現するテンプレートマッチングの基本とマルチスケール対応

テンプレート画像

PythonとOpenCVで実現するテンプレートマッチングの基本とマルチスケール対応

コード例

import cv2
import numpy as np

# 元画像を開いてグレースケールに変換
main_image = cv2.imread('main_image.png')
gray_image = cv2.cvtColor(main_image, cv2.COLOR_BGR2GRAY)

# テンプレートをグレースケールで開く
template = cv2.imread('template1.png', 0)
width, height = template.shape[::-1]  # 幅と高さを取得

# cv2.matchTemplateでマッチングを実行
match = cv2.matchTemplate(gray_image, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
position = np.where(match >= threshold)  # 閾値以上の位置を取得

# 一致したテンプレートの周囲に矩形を描画
for point in zip(*position[::-1]):
   cv2.rectangle(main_image, point, (point[0] + width, point[1] + height), (0, 204, 153), 0)

cv2.imshow('Template Found', main_image)
cv2.waitKey(0)

実行結果

PythonとOpenCVで実現するテンプレートマッチングの基本とマルチスケール対応

マルチスケール対応のマッチング

上記のコードは単一サイズのマッチングのみに対応しており、テンプレートと対象物のサイズが異なる場合は検出できません。そこで次に、マルチスケーリングを使った手法を紹介します。

このアプローチでは、元画像をさまざまなサイズに縮小・拡大しながら繰り返しマッチングを行い、最も相関係数の大きかったスケールを採用することで、サイズの異なるテンプレートでも位置を特定できます。

元画像は同じものを使用し、今回は以下のテンプレートを使います。

PythonとOpenCVで実現するテンプレートマッチングの基本とマルチスケール対応

コード例

import imutils
import cv2
import numpy as np

# テンプレートを開き、Canny法でエッジ検出
template = cv2.imread('template3.jpg')
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
template = cv2.Canny(template, 10, 25)
(height, width) = template.shape[:2]

# 元画像を開いてグレースケールに変換
main_image = cv2.imread('main_image.png')
gray_image = cv2.cvtColor(main_image, cv2.COLOR_BGR2GRAY)

temp_found = None
for scale in np.linspace(0.2, 1.0, 20)[::-1]:
   # 画像をリサイズし、比率を保存
   resized_img = imutils.resize(gray_image, width=int(gray_image.shape[1] * scale))
   ratio = gray_image.shape[1] / float(resized_img.shape[1])
   if resized_img.shape[0] < height or resized_img.shape[1] < width:
      break
   # エッジ検出した画像に変換してチェック
   e = cv2.Canny(resized_img, 10, 25)
   match = cv2.matchTemplate(e, template, cv2.TM_CCOEFF)
   (_, val_max, _, loc_max) = cv2.minMaxLoc(match)
   if temp_found is None or val_max > temp_found[0]:
      temp_found = (val_max, loc_max, ratio)

# temp_foundからx, y座標を算出
(_, loc_max, r) = temp_found
(x_start, y_start) = (int(loc_max[0]), int(loc_max[1]))
(x_end, y_end) = (int((loc_max[0] + width)), int((loc_max[1] + height)))

# テンプレートの周囲に矩形を描画
cv2.rectangle(main_image, (x_start, y_start), (x_end, y_end), (153, 22, 0), 5)
cv2.imshow('Template Found', main_image)
cv2.waitKey(0)

実行結果

PythonとOpenCVで実現するテンプレートマッチングの基本とマルチスケール対応

  1. PythonのOpenCVモジュールで画像に幾何学図形を描画する方法

    はじめに OpenCVの基本操作のひとつが「画像への描画」です。線、円、矩形(長方形)など、さまざまな幾何学形状を画像上に追加できます。 画像解析の現場では、画像の一部を強調表示したい場面がよくあります。たとえば、注目したい領域を囲む矩形を追加したり、特定の場所を指し示す矢印を描いたりするケースです。本記事では、PythonのOpenCVモジュールを使って画像に幾何学図形を描画する方法を、サンプルコードとともにわかりやすく解説します。 主な描画関数一覧 cv2.line() … 画像に直線を描画する関数 cv2.rectangle() … 画像に矩形を描画する関数 cv2.circle()

  2. PythonとOpenCVを使って動画を逆再生(リバース再生)する方法

    OpenCVは「Open Source Computer Vision(オープンソース・コンピュータビジョン)」の略称です。この強力なライブラリを活用することで、画像や動画に対してさまざまな操作を実行できます。OpenCVの主な応用分野顔認識システムモーショントラッキング(動体追跡)人工ニューラルネットワーク深層ニューラルネットワーク動画ストリーミング などOpenCVのインストール方法Windows環境では、以下のコマンドでインストールできます。pip install opencv-pythonLinux環境の場合は、次のコマンドを使用します。sudo apt-get install pyt