見出し画像

[Python]カスケード分類器で動画上から特定の画像を検出する[OpenCV]③

前回の記事でカスケード分類器の作成方法までを行いました。今回は作成した分類器をOpenCVで実装し、リアルタイムで動画上の映像から特定の人物を検出します。

検証環境

  • Windows10 ノートPCの内蔵カメラを使用(webカメラでも可)

  • Python 3.10.0

  • OpenCV 4.5.5

実装

OpenCVについては過去の記事でもいろいろ書いているので、そちらもご覧ください。

コード全文
けっこう短くまとまりました。

import cv2
cap = cv2.VideoCapture(0)

while True:
  # 1フレームずつ取得する。
    ret, frame = cap.read()
    key = cv2.waitKey(1) & 0xFF
    # img = cv2.imread(frame)
    cascade = cv2.CascadeClassifier('cascade.xml')
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    
    objects = cascade.detectMultiScale(gray, scaleFactor=1.01, minNeighbors=3)
    
    # 赤枠で対象をマーク
    # colorはBGR形式で指定する。(青、緑、赤)
    # thicknessは線の太さ 3pxで描画
    for(x, y, w, h) in objects:
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 200), thickness=3)
        
    # result.jpgを出力
    cv2.imwrite("result.png", frame)
    cv2.imshow('image', frame)

    # qキーが押されたらループを終了する
    if key == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

ポイント①カスケード分類器の読み込み

作成したカスケード分類器のxmlファイルはcv2.CascadeClassifierで読み込みます。

cascade = cv2.CascadeClassifier('cascade.xml')

ポイント②カラー画像をグレースケールに変換

cap.read()ではビデオキャプチャーした映像から1フレームずつを取り出し、frameに格納しています。

ret, frame = cap.read()

下記のコードで取得したカラー画像をグレースケールに変換し、grayに格納しています。cascade.detectMultiScale()がグレースケール画像を必要とすることが理由です。

 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

ポイント③物体の検出

今回最大のポイントではないかと思いますが、cascade.detectMultiScale()にてグレースケールに変換した画像から物体を検出し、objectsに格納しています。

  objects = cascade.detectMultiScale(gray, scaleFactor=1.01, minNeighbors=3)

ここで設定する引数が検出精度に影響します。多少の試行錯誤も必要ですが、最適な検出ができるように数値を調整します。
引数の詳細につきましては下記のサイトなどもご参照ください。

ポイント④検出結果を検出枠で表示

あとは検出結果をcv2.rectangle()で画像に描画します。
今回は赤色で検出枠を描画していますが、OpenCVでは色の描画はRGBではなく、BGRで表されます。そのため赤色の枠を表示したい場合は(0, 0, 200)のように指定します。

    for(x, y, w, h) in objects:
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 200), thickness = 3)

実行結果

実行して検知した画像がこちら。この服を着ている時は検出できて、ほかの服を着ている時や人がいないときは検出しないという結果になりました。

特定の人物が映るとすぐに検出

ほぼ狙い通りの結果でした。検出速度も速いのが特徴でしたし、上の人物が動画に映っている間は検出枠に補足され続けるといった形になりました。

結論:カスケード分類器は用途次第で使える

というわけで特定の人物の人物がカメラに映ったら検出するという動きに成功することは一応できました。
精度という面では深層学習に劣るのかもしれません。しかし厳密な精度を求める場合は結構少ないものです。少ない画像データでサクッと実装できる方法としてこういった手法も検討の一つではないでしょうか。
実際には、検出したらその物体名を表示させるとか、管理者にメールで画像を添付するといったことになるのかと思います。この辺はプログラム上で動作を考えていく必要がありますね。
興味のある方はOpenCVの動作も確認しつつ、お試しいただければ幸いです。


この記事が気に入ったらサポートをしてみませんか?