(第4回)Python + OpenCV で遊んでみる(リアルタイム顔検知編)

(第4回)Python + OpenCV で遊んでみる(リアルタイム顔検知編)

目次

はじめに

前回は、静止画において顔検出器を使い、顔を認識することが出来ました。
今度は動画でリアルタイムに顔検出をさせたいと思います。

動画について

まず動画は、静止画をパラパラアニメのように高速で映し出すことでスムーズに動いているように見えます。

その1コマの静止画をフレームといい、1秒間あたりに表示されるフレームの数によって表示速度(動きのなめらかさ)を表します。
通常、テレビ等は30fps(frame per second:1秒間に30コマ)で表示されています。

動画処理

動画処理は、1フレームごとに読込み、画像処理をして描画を繰り返します。

import cv2

#動画を読込み
#カメラ等でストリーム再生の場合は引数に0等のデバイスIDを記述する
video = cv2.VideoCapture('inputVideo.avi')

while video.isOpened():
    #フレームを読込み
    ret, frame = video.read()

    #フレームが読み込めなかった場合は終了(動画が終わると読み込めなくなる)
    if not ret: break

    #-----------------
    # 画像処理を記述する
    #-----------------

    #フレームの描画
    cv2.imshow('frame', frame)

    #qキーの押下で処理を中止
    key = cv2.waitKey(1) & 0xFF
    if key == ord('q'): break

#メモリの解放
video.release()
cv2.destroyAllWindows()

ここに前回、使用した顔検知のプログラムを追加します。

動画の場合は、高速な処理が要求されるため、カスケード型の識別器を利用することが多いです。

今回は顔を自動的にモザイク処理する処理も追加してみました。

import cv2

#動画を読込み
#カメラ等でストリーム再生の場合は引数に0等のデバイスIDを記述する
video = cv2.VideoCapture(0)

cascade_path = "haarcascade_frontalface_default.xml"
cascade = cv2.CascadeClassifier(cascade_path)

while video.isOpened():
    # フレームを読込み
    ret, frame = video.read()

    # フレームが読み込めなかった場合は終了(動画が終わると読み込めなくなる)
    if not ret: break
    # 顔検出
    facerect = cascade.detectMultiScale(frame, scaleFactor=1.1, minNeighbors=2, minSize=(30, 30))
    
    # 矩形線の色
    rectangle_color = (0, 255, 0) #緑色

    # 顔を検出した場合
    if len(facerect) > 0:
        for rect in facerect:
            cv2.rectangle(frame, tuple(rect[0:2]),tuple(rect[0:2] + rect[2:4]), rectangle_color, thickness=2)
            # 顔部分の抽出
            cut_frame = frame[rect[1]:rect[1]+rect[3],rect[0]:rect[0]+rect[2]]
            # サイズの縮小
            cut_frame = cv2.resize(cut_frame,(rect[2]//20, rect[3]//20))
            # 元のサイズにリサイズ。
            # cv2.INTER_NEAREST(最近傍補間)オプションを指定することで荒くなる。デフォルトでは cv2.INTER_LINEAR(バイリニア補間)となり、滑らかなモザイクとなる。
            cut_frame = cv2.resize(cut_frame,(rect[2], rect[3]),cv2.INTER_NEAREST)
            # 縮小→復元画像で元の画像と置換
            frame[rect[1]:rect[1]+rect[3],rect[0]:rect[0]+rect[2]]=cut_frame


    # フレームの描画
    cv2.imshow('frame', frame)

    # qキーの押下で処理を中止
    key = cv2.waitKey(1) & 0xFF
    if key == ord('q'): break

#メモリの解放
video.release()
cv2.destroyAllWindows()
動きが欲しくて顔だけ動かしてみました。

自動的に顔にモザイクが掛かっています。
ただし、顔検知が正面顔の検知しかしないため、横顔や後ろを向くとモザイクがはずれてしまいます。
横顔検知の検出器を組み合わせると横顔も隠せそうですね。

おわりに

今回は動画の読込み処理を行い、リアルタイムに顔検知を行い、画像処理(モザイク処理)を行いました。

動画を複数毎の静止画の集まりと考えれば、それほど複雑ではなく、他の画像処理を組み合わせることで色んな事が出来そうです。
アプリ等で自動的に猫耳が付いたり、顔を盛れるのも顔検知と画像処理を組み合わせて行っていることがわかりました。

次回は、YOLOを利用した物体検知を行ってみたいと思います。