【Python】 opencvを使って顔検出 PCカメラ編

Pythonに関する記事ですPython
Pythonに関する記事です

前回は写真から顔検出を行いましたが、今回はPCについているカメラまたはUSBカメラからリアルタイムで顔の検出を行うプログラムを紹介します。

実行結果

OS:Windows11

IDE:VS Code

言語:Python 3.10.9

パッケージ:opencv 4.6.0、qt-main 5.15.2

仮想環境:Miniconda

スポンサーリンク

事前準備

前回の作業フォルダ「python_work」内に「camera_face_detection.py」を新規追加します。仮想環境は「face_detection」となります。作業環境等の詳細は下記をご覧ください。

顔認証に使った画像は「写真AC」を利用しました。今回はPCに付いているカメラを利用しますので皆さんの顔が検出されるか確かめてください。

ソファーに座る三世代ファミリー2
ソファーに座る三世代ファミリー2(No: 23336923)の無料写真素材を提供する「写真AC」のフリー写真素材は、個人、商用を問わず無料でお使いいただけます。クレジット表記やリンクは一切不要です。Web、DTP、動画などの写真素材としてお使いください。

プログラミング

「camera_face_detection.py」にコードを記述します。

import cv2

# 分類器
cascade_path = 'opencv-master/data/haarcascades/haarcascade_frontalface_default.xml'

# 特徴量読み込み
cascade = cv2.CascadeClassifier(cascade_path)

# カメラ定義
cap = cv2.VideoCapture(0, cv2.CAP_MSMF)

while(True):
    # ビデオキャプチャ
    ret, frame = cap.read()
    # 顔検出
    faces = cascade.detectMultiScale(frame, scaleFactor=1.23, minNeighbors=3, minSize=(50, 50))
    # 検出した顔を囲む矩形の作成
    for x, y, w, h in faces:
        cv2.rectangle(frame, (x, y), (x+w, y+h), (127, 255, 0), 2)

    # 表示
    cv2.imshow('frame', frame)

    # qが押されたら終了
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# カメラ終了
cap.release()
# ウィンドウ終了
cv2.destroyAllWindows()

import

import cv2

opencvをプログラム内で使えるようにインポートします。

分類器の設定

# 分類器
cascade_path = 'opencv-master/data/haarcascades/haarcascade_frontalface_default.xml'

# 特徴量読み込み
cascade = cv2.CascadeClassifier(cascade_path)

cascade_path:顔検出用のファイルを設定します。「haarcascade_frontalface_default.xml」は正面の顔を検出するためのxmlファイルです。

cv2.CascadeClassifier():顔検出用のxmlファイルを読み込みます。

カメラの定義

# カメラ定義
cap = cv2.VideoCapture(0第1引数, cv2.CAP_MSMF第2引数)

cv2.VideoCapture():PCに接続されているカメラの設定を行います。

第1引数はカメラデバイスIDです。基本的に「0」で問題ありませんが複数のカメラやIRカメラがある場合は「1」の場合もあります。

第2引数は「apiPreference」を設定します。OS等でAPIが異なるのでここで指定します。Windowsであれば「cv2.CAP_MSMF」macOSであれば「cv2.CAP_AVFOUNDATION」と入力します。

OpenCV: Flags for video I/O

macではエラーは出なかったのですがWindowsでは下記のエラーが発生しますが動作に影響はありません。

QMimeDatabase: Error loading internal MIME data
An error has been encountered at line 1 of <internal MIME data>: Premature end of document.:

ビデオキャプチャ

# ビデオキャプチャ
ret第1戻り値, frame第2戻り値 = cap.read()

read():先ほどカメラの定義を行った「cap」を使ってビデオキャプチャを行います。

第1戻り値「ret」にはキャプチャ(画像取得)が成功したか結果が入ります。成功:True、失敗:False

第2戻り値「frame」には画像データ(1フレーム)が入ります。

顔の検出

# 顔検出
faces戻り値 = cascade.detectMultiScale(frame第1引数, scaleFactor=1.23第2引数, minNeighbors=3第3引数, minSize=(50, 50)第4引数)

detectMultiScale():特徴量を読み込んだ「cascade」を使って検出を行います。

第1引数は検出する画像を指定します。

第2引数「scaleFactor」は画像サイズをどれくらい縮小して検出を行うかを設定します。「1.1」は10%まで縮小します。設定できる範囲は「1.0 < scaleFactor」、1.0に近いほど処理が重くなります。

第3引数「minNeighbors」は候補となる矩形に含まれる近傍矩形の数を設定します。「3」は近傍矩形が3つないと候補から除外されます。設定できる範囲は「0 <= minNeighbors」0だと精度が下がります。

第4引数「minSize」は候補となる矩形サイズが設定値以下だと候補から除外されます。サイズはpixel単位となります。

戻り値「faces」には検出した顔の座標が入ります。

検出した顔を囲む矩形の作成

# 検出した顔を囲む矩形の作成
for x, y, w, h in faces:
    cv2.rectangle(frame第1引数, (x, y第2引数), (x+w, y+h第3引数), (127, 255, 0第4引数), 2第5引数)

rectangle():長方形を描画します。

第1引数「frame」は描画する画像を指定します。

第2引数「(x, y)」は長方形を描画する座標1を指定します。pixel単位となります。

第3引数「(x+w, y+h)」は長方形を描画する座標1を指定します。pixel単位となります。

第4引数「(127, 255, 0)」は長方形を描画する色を指定します。RGBで指定します。

第5引数「2」は長方形を描画する太さを指定します。pixel単位となります。

表示処理

# 表示
cv2.imshow('frame第1引数', frame第2引数)

imshow():画面へ表示します。

第1引数「’frame’」画面に表示するウィンドウ名を指定します。

第2引数「frame」実際に表示する画像を指定します。

ブレイク処理

# qが押されたら終了
if cv2.waitKey(1第1引数) & 0xFF == ord('q'):
    break

waitKey():表示している画面でキーイベントの発生を待ちます。

第1引数「1」は1ミリ秒待機となります。

条件式「0xFF == ord(‘q’)」キーボードの「q」が押下されたかを判定します。

キーボードの「q」が押下されたらwhile文を抜けます。

後処理

# カメラ終了
cap.release()
# ウィンドウ終了
cv2.destroyAllWindows()

release():カメラを終了します。

destroyAllWindows():ウィンドウを閉じます。

プログラムの実行

python camera_face_detection.py

ウィンドウにカメラ画像が表示され顔を検出すると枠線で囲まれるます。

終了はキーボードの「q」を押下します。

まとめ

カメラ画像をリアルタイムで表示しながら顔の検出を行うプログラムが20行程度で出来てしまいます。

Haar Cascade識別器を変えることで瞳の検出や人物の検出等行うことができます。

色々試してみてください。

中澤 一人

沖縄支店の中澤です。
プログラミング講師やシステム開発を行っています。

#有限会社エヌ・ユー・エスをフォローする

コメント

タイトルとURLをコピーしました