PythonとOpenCVで実現するテンプレートマッチングの基本とマルチスケール対応
テンプレートマッチングとは、実際の画像の中から、あらかじめ用意した小さな画像(テンプレート)と一致する部分を探し出す技術です。基本的にはパターンマッチングの一種であり、物体検出や顔認識など、さまざまなコンピュータビジョンのタスクの基礎となる手法です。
PythonではOpenCVモジュールを使うことで、このマッチング処理を簡単に実装できます。本記事では、OpenCVのテンプレートマッチング機能を使った具体的な方法を解説します。
OpenCVのインストール
OpenCVの機能を利用するには、まずpipでライブラリをインストールします。
sudo pip3 install opencv-python
閾値(スレッショルド)の重要性
テンプレートマッチングには「どの程度一致していれば検出とみなすか」を決める精度係数、いわゆる閾値(threshold)が存在します。
例えば、目や顔のパーツの画像をテンプレートとして渡せば、顔認識的な仕組みを作ることも可能です。しかし、人の目は一人ひとり形が異なるため、精度レベルを100%に設定するとほとんど何も検出できません。逆に50%程度に緩めると、より多くの候補を検出できます。一般的には、80%前後の精度レベルが多くの場面で使われています。
テンプレートマッチングの手順
元画像を読み込み、グレースケール画像に変換する。
テンプレートもグレースケール画像として読み込む。
テンプレートを元画像上でスライドさせながら、一致度が高い位置を探す。
結果が設定した閾値以上であれば、その位置を検出箇所としてマークする。
基本的なサンプルコード
まず、以下の元画像とテンプレート画像を用意します。
元画像

テンプレート画像

コード例
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)実行結果

マルチスケール対応のマッチング
上記のコードは単一サイズのマッチングのみに対応しており、テンプレートと対象物のサイズが異なる場合は検出できません。そこで次に、マルチスケーリングを使った手法を紹介します。
このアプローチでは、元画像をさまざまなサイズに縮小・拡大しながら繰り返しマッチングを行い、最も相関係数の大きかったスケールを採用することで、サイズの異なるテンプレートでも位置を特定できます。
元画像は同じものを使用し、今回は以下のテンプレートを使います。

コード例
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モジュールで画像に幾何学図形を描画する方法
はじめに OpenCVの基本操作のひとつが「画像への描画」です。線、円、矩形(長方形)など、さまざまな幾何学形状を画像上に追加できます。 画像解析の現場では、画像の一部を強調表示したい場面がよくあります。たとえば、注目したい領域を囲む矩形を追加したり、特定の場所を指し示す矢印を描いたりするケースです。本記事では、PythonのOpenCVモジュールを使って画像に幾何学図形を描画する方法を、サンプルコードとともにわかりやすく解説します。 主な描画関数一覧 cv2.line() … 画像に直線を描画する関数 cv2.rectangle() … 画像に矩形を描画する関数 cv2.circle()
-
PythonとOpenCVを使って動画を逆再生(リバース再生)する方法
OpenCVは「Open Source Computer Vision(オープンソース・コンピュータビジョン)」の略称です。この強力なライブラリを活用することで、画像や動画に対してさまざまな操作を実行できます。OpenCVの主な応用分野顔認識システムモーショントラッキング(動体追跡)人工ニューラルネットワーク深層ニューラルネットワーク動画ストリーミング などOpenCVのインストール方法Windows環境では、以下のコマンドでインストールできます。pip install opencv-pythonLinux環境の場合は、次のコマンドを使用します。sudo apt-get install pyt