【Python】OpenCVを利用したカメラ映像や動画から顔認識・顔検出を行う方法

時計 2022.10.24 / 時計

【Python】OpenCVを利用したカメラ映像や動画から顔認識・顔検出を行う方法

記事ではPythonOpenCVによる、カメラの映像や動画からリアルタイムで顔認識・顔検出を行う方法について解説していきます。

OpenCVとは画像処理や動画処理、画像解析に利用されるライブラリです。顔認識や文字認識(OCR)、機械学習など様々な分野で利用されている人気のあるライブラリです。

パソコン内蔵カメラの映像や動画から顔認識・検出するような高度なプログラムも、OpenCVを使うと非常に簡単に作ることができます。

ぜひ本記事を通して、OpenCVで動画の顔認識方法について理解を深めてください。

カメラ映像や動画から顔認識を行う流れ

動画はいわばその瞬間をとらえた静止画を続けて流している、と言えます。そこでプログラムには、一瞬の静止画に対して顔認識を行い、顔があれば枠で囲む、という作業を行わせます。

これによりカメラ映像などの動画に対して顔認識を行っていくプログラムをここでは作成していきます。

具体的には以下の流れでリアルタイムのカメラ映像から顔認識を行います。

  1. 顔認識用の学習済みモデルを読み込む
  2. カメラ映像や動画から画像データを取得する
  3. 画像をグレースケール化(白黒化)する
  4. 画像から顔を検出しその位置を取得する
  5. 検出した顔の位置に目印の枠をつける
  6. 顔認識した画像を表示する

上記の流れ2~6をプログラムが終了するまで続けていきます。

画像から顔認識を行う方法を理解していると、今回の動画での顔認識が理解しやすいです。画像からの顔認識をまだ行ったことがない方は、ぜひ以下記事をご参照ください。

顔認識用の学習済みモデル(カスケード分類機)を読み込む

顔認識に利用する学習済みモデル(カスケード分類機)はCascadeClassifier()メソッドを使って読み込みます。ここでは学習済みモデルとして、OpenCVに備わっている「haarcascade_frontalface_default.xml」を使用します。

学習済みモデルについては以下記事をご参照ください。

import cv2
# 学習済みモデルの読み込み
cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")

カメラ映像や動画から画像データを取得する

VideoCaptureオブジェクトの取得

カメラ映像や動画ファイルから画像データを取得するには、まずcv2. VideoCapture()を利用します。

構文

cv2.VideoCapture(引数)

cv2.VideoCapture()の返り値はVideoCaptureオブジェクトです。カメラ映像であれば引数にパソコンのカメラ番号を指定します。ノートパソコンに内蔵されているカメラであれば0、USBで接続したカメラは1を指定します。

動画ファイルであれば引数にファイル名を絶対パスまたは相対パスで指定します。動画ファイルはMP4やAVI、FLVなどに対応しています。

VideoCaptureオブジェクトは以下のように変数に格納しましょう。

# カメラ映像からVideoCaptureオブジェクトを取得
cap = cv2.VideoCapture(0)

動画の読み込みができているかの判定

VideoCapture()で動画が問題なく読み込みできているかをVideoCaptureクラスのisOpened()メソッドを使って確認できます。

読み込みに問題がなければTrueを返します。プログラムではif判定を使って以下のように記述します。

import cv2

# 学習済みモデルの読み込み
cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
# カメラ映像からVideoCaptureオブジェクトを取得
cap = cv2.VideoCapture(0)
# カメラに問題がないかの確認
if not cap.isOpened():
    print("カメラが正常ではありません")
    exit()

動画から画像データを取得

カメラ映像や動画から1コマ分の画像データを取得するためにVideoCaptureクラスのread()メソッドを使います。

read()メソッドの返り値はBool値(TrueまたはFalse)とキャプチャした画像データです。以下のように二つの変数に格納します。またここではカメラから連続的にキャプチャ画像を取得するためにwhile True:内に記述しています。

while True:
    # Bool値とキャプチャ画像を変数に格納
    ret, frame = cap.read()

Bool値は正しく画像データが読み込めればTrueを返します。if判定を使って、画像データが正しく読み込めていなければwhile文をbreakで抜けるようにしましょう。

import cv2

# 学習済みモデルの読み込み
cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
# カメラ映像からVideoCaptureオブジェクトを取得
cap = cv2.VideoCapture(0)
# カメラに問題がないかの確認
if not cap.isOpened():
    print("カメラが正常ではありません")
    exit()
# カメラから連続的にキャプチャ画像を取得
while True:
    # Bool値とキャプチャ画像を変数に格納
    ret, frame = cap.read()
    # キャプチャ画像が正しく読み込めたかの確認
    if not ret:
        print("画像を正しく読み込めませんでした")
        break

画像をグレースケール化(白黒化)する

画像からノイズを除去して誤認識を少なくするためにグレースケール化(白黒)します。

グレースケール化するにはcvtColor()メソッドを利用します。以下のようにして読み込んだ画像をグレースケール化しましょう。

# 画像データをグレースケール化(白黒)
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

画像から顔を検出しその位置を取得する

cv2.CascadeClassifier.detectMultiScaleメソッドを使用して検出した顔の位置を取得します。

# 顔を検出する
lists = cascade.detectMultiScale(frame_gray, minSize=(50, 50))

検出した顔の位置に目印の枠をつける

検出した顔の位置情報から画像にある顔に目印の枠をつけていきます。以下ではrectangle()メソッドを使って、赤い長方形で検出した顔を囲むようにしています。

# forですべての顔を赤い長方形で囲む
for (x,y,w,h) in lists:
    cv2.rectangle(frame, (x,y), (x+w, y+h), (0, 0, 255), thickness=2)

顔認識した画像を表示する

顔認識した画像を表示するにはimshow()メソッドを使用します。

imshow()の第一引数window_nameには表示されるウィンドウの名前、第二引数imageにはキャプチャ画像に赤い枠を書き込んだframeを指定します。

# 顔認識を行っている画像を表示
cv2.imshow('video image', frame)

プログラムの全体ソースコード

ここまでがOpenCVでカメラ画像や動画から顔認識を行う方法になります。

実際のプログラムではwhileループを抜けるための記述をする必要があります。以下に載せるスクリプトでは「q」キーがタイプされたら break するための if 文を記述しています。

import cv2

# 学習済みモデルの読み込み
cascade = cv2.CascadeClassifier("C:\EAS\haarcascade_frontalface_default.xml")
# カメラ映像からVideoCaptureオブジェクトを取得
cap = cv2.VideoCapture(0)
# カメラに問題がないかの確認
if not cap.isOpened():
    print("カメラが正常ではありません")
    exit()
# カメラから連続的にキャプチャ画像を取得
while True:
    # Bool値とキャプチャ画像を変数に格納
    ret, frame = cap.read()
    # キャプチャ画像が正しく読み込めたかの確認
    if not ret:
        print("画像を正しく読み込めませんでした")
        break
    # 画像データをグレースケール化(白黒)
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # 顔を検出する
    lists = cascade.detectMultiScale(frame_gray, minSize=(50, 50))
    # forですべての顔を赤い長方形で囲む
    for (x,y,w,h) in lists:
        cv2.rectangle(frame, (x,y), (x+w, y+h), (0, 0, 255), thickness=2)
    # 顔認識を行っている画像を表示
    cv2.imshow('video image', frame)
    # qが押されたらwhileから抜ける
    if cv2.waitKey(1) == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()