Raspberry Pi3とPicameraでリアルタイム顔認識

Raspberry Pi3とPicameraを使ってリアルタイム顔認識・画像上書きを行ってみた。

内容はもう出尽くした感がありますが、PythonOpenCVを使っています。

いろんなサイトを見てはコピペ実行で作ったのでわからないまま作ってしまったのですが、

コメントを入れながら1行ずつ理解した感じです。

# coding:utf-8

import io
import picamera
import cv2

import numpy as np

# HAAR分類器の顔検出用の特徴量
cascade_path = "/usr/share/opencv/haarcascades/haarcascade_frontalface_alt.xml"

# カスケード分類器の特徴量を取得する
cascade = cv2.CascadeClassifier(cascade_path)

stream = io.BytesIO()

CAMERA_WIDTH = 320
CAMERA_HEIGHT = 240

color = (255,255,255)

camera = picamera.PiCamera()
camera.resolution = (CAMERA_WIDTH, CAMERA_HEIGHT)

laugh = cv2.imread('laughingman.png', -1)  # 画像の読み込み。-1でアルファチャンネルを付けて読む
mask = cv2.cvtColor(laugh[:,:,3], cv2.cv.CV_GRAY2BGR)/255.0  # 画像からアルファチャンネルだけを抜き出して0から1までの値にする。あと3チャンネルにしておく
laugh = laugh[:,:,:3]  # アルファチャンネルを消したもの

while True:
        camera.capture(stream, format='jpeg')
        data = np.fromstring(stream.getvalue(), dtype=np.uint8)
        image = cv2.imdecode(data, 1)
        cv2.imshow('image',image)
        cv2.waitKey(16)

        # グレースケール変換
        image_gray = cv2.cvtColor(image, cv2.cv.CV_BGR2GRAY)

        # 物体認識(顔認識)の実行
        # image – CV_8U 型の行列.ここに格納されている画像中から物体が検出されます
        # objects – 矩形を要素とするベクトル.それぞれの矩形は,検出した物体を含みます
        # scaleFactor – 各画像スケールにおける縮小量を表します
        # minNeighbors – 物体候補となる矩形は,最低でもこの数だけの近傍矩形を含む必要があります
        # flags – このパラメータは,新しいカスケードでは利用されません.古いカスケードに対しては,cvHaarDetectObjects 関数の場合と同じ意味を持ちます
        # minSize – 物体が取り得る最小サイズ.これよりも小さい物体は無視されます
        # facerect = cascade.detectMultiScale(image_gray, scaleFactor=1.1, minNeighbors=3, minSize=(10, 10), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)

        facerect = cascade.detectMultiScale(image_gray, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1))

        image_output = image
        if len(facerect) > 0:


                # 検出した顔を囲む矩形の作成
                for rect in facerect:

                        # 画像のサイズ調整
                        rect[0] -= min(25, rect[0])
                        rect[1] -= min(25, rect[1])
                        rect[2] += min(50, image_output.shape[1]-(rect[0]+rect[2]))
                        rect[3] += min(50, image_output.shape[0]-(rect[1]+rect[3]))

                        # 笑い男とマスクを認識した顔と同じサイズにリサイズする。
                        laugh2 = cv2.resize(laugh, tuple(rect[2:]))
                        mask2 = cv2.resize(mask, tuple(rect[2:]))

                        # 笑い男の合成。
                        image_output[rect[1]:rect[1]+rect[3], rect[0]:rect[0]+rect[2]] = laugh2[:,:] * mask2 + image_output[rect[1]:rect[1]+rect[3], rect[0]:rect[0]+rect[2]] * (1.0 - mask2)
        cv2.imshow('image_out',image_output)
        cv2.waitKey(16)

        stream.seek(0)

        if cv2.waitKey(10) > 0:
            break

cv2.destroyAllWindows()

参考にさせていただいたサイトはこちら。 そのまんまのコピペで動きました。ありがとうございました。 peaceandhilightandpython.hatenablog.com

pythonのOpenCVでリアルタイムに笑い男 - BlankTar


結果はこちら! f:id:tomtech:20170603161049p:plain

思った通りの内容でした。 横顔の認識は今回読み込んだライブラリではできなかったです。

攻殻機動隊SAC笑い男の書き替え技術スゲーなーとあらためて思ったり・・・

HAAR分類器とかカスケード分類器とかまだまだわかっていない部分が多いですが、 これから中身を見ていきます。