OpenCV は、コンピュータビジョン分野で非常に人気のあるライブラリです。画像処理、動画分析、物体検出など、幅広いタスクに対応できます。この記事では、Python と OpenCV を使用して、画像や動画の中から人物を検出する方法を具体的に解説します。
- OpenCV とは
- OpenCV のインストール
- 人物検出の手法
- 実践:Haar Cascade を用いた人物検出
- 応用: HOG + SVM を用いた人物検出
- リアルタイム人物検出 (Web カメラ)
- まとめ
OpenCV とは
OpenCV (Open Source Computer Vision Library) はオープンソースのコンピュータビジョンライブラリです。画像処理、動画解析、物体検出(顔認識、人物検出など)、特徴量抽出、機械学習、カメラキャリブレーションなど、多様な機能を備えています。C++, Python, Java など、複数のプログラミング言語で利用でき、Windows, macOS, Linux, Android, iOS など、さまざまなプラットフォームで動作します。Apache License 2 のもとで公開されているため、商用・非商用を問わず、自由に利用できます。
OpenCV のインストール
OpenCV は、pip コマンドで簡単にインストールできます。
pip install opencv-python pip install opencv-contrib-python
opencv-pythonはOpenCVの主要モジュールで、opencv-contrib-pythonは追加モジュールです。より高度な機能や実験的な機能を利用したい場合は、opencv-contrib-python パッケージもインストールすることを推奨します。
人物検出の手法
OpenCV で人物検出を行う主な手法には、Haar Cascade (ハールカスケード) と HOG + SVM (Histogram of Oriented Gradients + Support Vector Machine) があります。OpenCV には、これらの手法のための学習済みモデルが用意されているため、すぐに人物検出を試すことができます。
| 手法 | 特徴 | メリット | デメリット |
|---|---|---|---|
| Haar Cascade | 多数の Haar-like 特徴(白黒矩形パターン)と AdaBoost を組み合わせたカスケード分類器を使用。 | 比較的処理が高速。リアルタイム処理に適している。 | 精度は比較的新しい手法に劣る場合がある。照明変化、姿勢、遮蔽物に弱い。 |
| HOG + SVM | 画像の輝度勾配の方向と強さをヒストグラム化した HOG 特徴量と、SVM を用いて人物とそれ以外を分類。 | Haar Cascade より精度が高い傾向。照明変化や多少の姿勢変化に比較的強い。 | Haar Cascade より計算コストが高い場合がある。 |
実践:Haar Cascade を用いた人物検出
まずは、比較的シンプルな Haar Cascade を使った人物検出から始めます。
1. 基本的な人物検出
OpenCV を使用して、画像 (person.jpg) から Haar Cascade 分類器を用いて人物を検出し、検出結果を矩形で囲んで表示する処理を行います。
import cv2 # 画像の読み込み image = cv2.imread('person.jpg') # 任意の画像ファイル名に置き換え # グレースケール変換 gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Haar Cascade 分類器の読み込み cascade = cv2.CascadeClassifier('haarcascade_fullbody.xml') # 人物検出の実行 rects = cascade.detectMultiScale(gray_image) # 検出された人物を矩形で囲む for (x, y, w, h) in rects: cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) # 結果の表示 cv2.imshow('Detected Person', image) cv2.waitKey(0) cv2.destroyAllWindows()
detectMultiScale() 関数は、CascadeClassifier オブジェクトのメソッドで、グレースケール画像 (gray_image) 中から物体(ここでは人物)を検出します。ここでは、rects = cascade.detectMultiScale(gray_image) の部分で処理を実行しています。検出結果は、人物の位置とサイズを表す矩形のリスト (rects) として得られます。各矩形は、(x, y, w, h) の形式で、x, y は矩形の左上隅の座標、w は幅、h は高さを表します。
このコードでは、まず cv2.imread('person.jpg') で画像ファイルを読み込み、cv2.cvtColor() でグレースケールに変換しています。Haar Cascade はグレースケール画像を処理対象とするため、この変換が必要です。次に、cv2.CascadeClassifier('haarcascade_fullbody.xml') で、OpenCV に付属の学習済み Haar Cascade 分類器を読み込みます。そして、detectMultiScale() で人物を検出し、 cv2.rectangle() で検出された人物の周囲に緑色の矩形を描画します。最後に、cv2.imshow(), cv2.waitKey(), cv2.destroyAllWindows() で結果を表示し、ウィンドウを閉じます。
2. 検出パラメータの調整
detectMultiScale()関数のパラメータを設定し、検出精度を調整します。
rects = cascade.detectMultiScale(
gray_image,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30)
)
detectMultiScale() 関数は、パラメータで指定された条件で人物検出を行います。scaleFactor=1.1 は、画像を 10% ずつ縮小しながら人物を探索することを意味します。この値を小さくすると検出率は上がりますが、処理時間は長くなります。minNeighbors=5 は、検出結果の信頼性に関する閾値で、5 つの近傍矩形と重なっている場合に検出結果として採用します。値を大きくすると誤検出は減りますが、検出漏れが増加する可能性があります。
minSize=(30, 30) は、検出する人物の最小サイズを (幅, 高さ) で指定します。これらのパラメータを調整することで、状況に応じた検出精度と処理速度のバランスを実現できます。
3. 複数の人物の検出
複数の人物が写っている画像を対象に、全身検出と上半身検出の両方を行い、それぞれの検出結果を異なる色で表示します。
import cv2 image = cv2.imread('people.jpg') # 複数の人物がいる画像を想定 gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 全身検出用の分類器 fullbody_cascade = cv2.CascadeClassifier('haarcascade_fullbody.xml') fullbody_rects = fullbody_cascade.detectMultiScale(gray_image, scaleFactor=1.1, minNeighbors=3, minSize=(30, 30)) # 上半身検出用の分類器 (必要に応じて) upperbody_cascade = cv2.CascadeClassifier('haarcascade_upperbody.xml') upperbody_rects = upperbody_cascade.detectMultiScale(gray_image, scaleFactor=1.1, minNeighbors=3, minSize=(30, 30)) # 検出結果の描画 (全身) for (x, y, w, h) in fullbody_rects: cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) # 検出結果の描画 (上半身) for (x, y, w, h) in upperbody_rects: cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2) cv2.imshow('Detected People', image) cv2.waitKey(0) cv2.destroyAllWindows()
全身検出は fullbody_rects = fullbody_cascade.detectMultiScale(...)、上半身検出は upperbody_rects = upperbody_cascade.detectMultiScale(...) で行われます。それぞれの detectMultiScale() 関数は、異なる分類器(全身用:haarcascade_fullbody.xml、上半身用:haarcascade_upperbody.xml)を用いて、画像中から人物または上半身を検出します。
このコードでは、異なる分類器を読み込むために cv2.CascadeClassifier() が複数回呼び出しています。また、検出結果を区別するため、cv2.rectangle() で描画する矩形の色を変えています(全身は緑、上半身は赤)。これにより、どの分類器がどの部分を検出したかが一目でわかるようになります。
応用: HOG + SVM を用いた人物検出
このコードでは、HOG + SVMを用いて人物検出を行います。
import cv2 # HOGDescriptor オブジェクトの作成 hog = cv2.HOGDescriptor() # 学習済みの SVM 分類器を設定 hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) # 画像の読み込み image = cv2.imread("person.jpg") # 人物検出 (rects, weights) = hog.detectMultiScale( image, winStride=(4, 4), padding=(8, 8), scale=1.05 ) # 信頼度の高い結果のみ描画 for (x, y, w, h), weight in zip(rects, weights): if weight > 0.5: cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.imshow("HOG + SVM Person Detection", image) cv2.waitKey(0) cv2.destroyAllWindows()
人物検出は、(rects, weights) = hog.detectMultiScale(...)の部分で行われています。hog.detectMultiScale()は、HOGDescriptorオブジェクトのメソッドであり、HOG特徴量とSVM(サポートベクターマシン)を用いて人物を検出します。検出結果として、人物の位置とサイズを表す矩形(rects)と、各矩形の信頼度(weights)が返されます。
最初にcv2.HOGDescriptor()でHOG特徴量を計算するためのオブジェクトを作成します。その後、
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())で、学習済みの人物検出器をSVM分類器として設定します。
hog.detectMultiScale()のパラメータ、winStrideは検出ウィンドウをスライドさせる際のステップサイズ、paddingは検出ウィンドウの周囲に追加するパディング、scaleは画像スケールをどれだけ縮小するかを表します。最後に、if weight > 0.5:で、信頼度が0.5より大きい検出結果のみを緑色の矩形で描画しています。
リアルタイム人物検出 (Web カメラ)
Web カメラからの映像に対してリアルタイムに人物検出を行います。
import cv2 #Haar Cascadeの設定 cascade = cv2.CascadeClassifier('haarcascade_fullbody.xml') # Web カメラの起動 cap = cv2.VideoCapture(0) # 0 は内蔵カメラ while True: ret, frame = cap.read() if not ret: break gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) rects = cascade.detectMultiScale(gray_frame, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)) for (x, y, w, h) in rects: cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.imshow('Real-time Person Detection', frame) if cv2.waitKey(1) & 0xFF == ord('q'): # 'q' キーで終了 break cap.release() cv2.destroyAllWindows()
while ループ内で、Web カメラからフレームを読み込み(cap.read())、グレースケールに変換(cv2.cvtColor())し、Haar Cascade 分類器を用いて人物検出(cascade.detectMultiScale())を実行します。検出された人物は矩形で囲まれ(cv2.rectangle())、結果が表示されます(cv2.imshow())。この一連の処理が繰り返し行われます。
cv2.VideoCapture(0) で Web カメラを起動し(通常、0 は内蔵カメラ)、'q' キーが押されたら (if cv2.waitKey(1) & 0xFF == ord('q'):) ループを終了し、cap.release() でカメラを解放、cv2.destroyAllWindows() でウィンドウを閉じます。
まとめ
この記事では、PythonとOpenCVを用いた人物検出について、Haar CascadeとHOG+SVMの2つの手法を解説しました。Haar Cascadeは高速でリアルタイム処理に適しており、HOG+SVMは精度が高い傾向があります。OpenCVの人物検出は、監視カメラシステム、人数カウント、マーケティング分析、ロボット工学、自動運転など、さまざまな分野で応用されています。Pythonでのコンピュータビジョンは下記のサイトでわかりやすく学習することができます。
[PR]