Raspberry Pi と Python と カメラで【笑顔判定機】を作ろう

electric

今回は、ラズパイにカメラを接続し、
笑顔になったら、ラズパイのスピーカーからお喋りをさせてみます。

朝一に笑顔を作って、素敵な一日にしたり、
笑顔溢れる家庭にしてみませんか?
ゲームに使っても楽しいかも♪

この記事で以下が学べます。

  • Python
  • 物体検出(OpenCV)
  • 音声合成

やりたいこと

・カメラが人の笑顔を検出すると、
・「いい笑顔ですね」とスピーカーから発話する

システム構成図

やることリスト

上記の「やりたいこと」をみて、
どんな作業が必要か、自分で項目を考えてみてください。
これを考えることで、「プログラミング的思考」が身に付いていきます。

番号作業項目備考
1やりたいこと・システム構成図の作成
2やることリストの作成作業項目の洗い出し
3部品の準備
4笑顔検出物体検出(OpenCV)使用
5音声合成
6以上の機能をまとめて、
やりたいことを実現する!

部品の準備

今回のシステムに必要な部品です。
不足している部品があれば購入下さい。

部品名備考
Raspberry Pi別途、電源・SDカード・HDMIケーブルが必要です。
スピーカーダイソーのUSBミニスピーカー(300円)がお薦めです。
ラズパイカメラRaspberry Pi専用カメラです。
今後、モーターを使ってカメラを動かしたいので、
「Raspberry Pi用遠隔操作カメラキット」を購入します。

購入に必要な部品を、
Raspberry Pi 関連に記載しています。

ラズパイは、電源を入れただけでは起動しません。
ラズパイの起動手順の記事を参照ください。

笑顔検出

笑顔を検出する為に、OpenCV(Open Source Computer Vision Library)の、
【物体検出】の機能を使って行きます。
OpenCVは、インテルが開発したオープンソースの画像処理ライブラリです。

笑顔を検出するまでの作業は、以下通りです。
・ラズパイ専用カメラを使う為に、カメラ機能を有効にする
・ラズパイに、OpenCVライブラリをインストールする
・物体検出用の特徴量データのダウンロード
・笑顔を判別するプログラムの作成

その前に、OpenCVで出来ることを確認してみましょう。

OpenCV出来ること一覧

  • 画像の読み込み・表示
  • 画像の作成・保存
  • 画像のトリミング・リサイズ・重ね合わせ
  • 画像の回転・上下反転・左右反転
  • グレースケール変換・色チャンネル分解・減色処理
  • モザイク処理・マスク処理・2枚の画像を合成
  • 図形の描画・文字の描画
  • ノイズ除去・平滑化・ぼかしフィルタ・メディアンフィルタ・ガウシアンフィルタ
  • 物体検出
  • テンプレートマッチング

以下記事を参考にしています。
●OpenCVにできることとは?OpenCVの特徴を徹底解説!
https://ai-kenkyujo.com/2021/04/09/opencvtoha/

カメラ機能の有効化

ラズパイ専用カメラを使う為に、カメラ機能を有効にします。

左上の「ラズパイアイコン」 → 「設定」→「Raspberry Piの設定」を選択。

「インターフェイス」タブ → カメラの有効/無効ボタンを「有効」を選択し、
画面右下の「OK」ボタン(画面切れてますが・・・)を押します。
ラズパイを再起動すると設定が反映されます。

OpenCVのインストール

以下コマンドを使って、ライブラリをインストールします。
すみません、ここはちょっと自信ないです。。。色々試したので。

プログラムを実行してエラーが出たら、
エラーが出たライブラリをインストールしてみてください。

sudo apt install python3-opencv

「no module named cv2」というエラーが出たら、
pip3 install opencv-python
をインストールしてみてください。

「libcblas.so.3: cannot open shared object files」というエラーが出たら、
sudo apt install libatlas-base-dev
をインストールしてみてください。

カスケード分類器の取得

カメラで撮った画像が何かを判別する為に、
物体の特徴量をまとめたデータ(カスケード分類器)を取得します。
その中に、人の顔や、笑顔の特徴量が含まれています。

カスケード分類器のダウンロード

以下 OpenCV URLから、ダウンロードします。
https://github.com/opencv/opencv/

「Code」→「Download ZIP」を押して、
ダウンロードを行います。

解凍

以下コマンドで回答する。

unzip opencv-master.zip

カスケード分類器は、解凍した以下フォルダ内に入っています。

./opencv-master/data/haarcascades

カスケード分類器一覧

カスケード分類器の一例を上げます。
他にもありますよ。

ファイル名検出物
haarcascade_smile.xml笑顔
haarcascade_frontalface_alt.xml正面の顔
haarcascade_eye.xml
haarcascade_fullbody.xml全身
haarcascade_eye_tree_eyeglasses.xml眼鏡
haarcascade_frontalcatface.xml猫の顔

プログラム

以下ディレクトリ通り、ディレクトリとファイルを作成する。
この章では、以下赤字のファイルを修正する。

/home/pi/work/camera_smile/
└camera.py

camera.py

# -*- coding: utf-8 -*-
import picamera
import picamera.array
import cv2 as cv

class Camera:

    def __init__(self):
        # カメラインスタンスの生成
        self.camera = picamera.PiCamera()
        # 画像インスタンスの生成
        self.stream = picamera.array.PiRGBArray(self.camera)
        self.camera.resolution = (512, 384)

    def detect_smile(self):
        detect = False

        # カメラ画像の取得
        self.camera.capture(self.stream, 'bgr', use_video_port=True)
        # grayに変換
        grayimg = cv.cvtColor(self.stream.array, cv.COLOR_BGR2GRAY)

        # 顔・笑顔検出の為、特徴量の読み込み
        face_cascade = cv.CascadeClassifier('/home/pi/Downloads/opencv-master/data/haarcascades/haarcascade_frontalface_default.xml')
        smile_cascade = cv.CascadeClassifier('/home/pi/Downloads/opencv-master/data/haarcascades/haarcascade_smile.xml')
        # 顔・笑顔検出
        faces = face_cascade.detectMultiScale(grayimg, scaleFactor=1.2, minNeighbors=2, minSize=(250, 250))
        smiles = smile_cascade.detectMultiScale(grayimg, scaleFactor=1.2, minNeighbors=5, minSize=(40, 40))

        # 顔を検出した場合
        if len(faces) >= 1:
            # 検出した箇所に赤色枠を描画する
            for rect in faces:
                cv.rectangle(self.stream.array, tuple(rect[0:2]), tuple(rect[0:2]+rect[2:4]), (0, 0, 255), thickness=3)
            # 笑顔を検出した場合
            if len(smiles) >= 3:
                # 検出した箇所に緑色枠を描画する
                for rect in smiles:
                    cv.rectangle(self.stream.array, tuple(rect[0:2]), tuple(rect[0:2]+rect[2:4]), (0, 255, 0), thickness=3)
                detect = True

        # 画像をWindowに表示
        cv.imshow('camera', self.stream.array)

        # 画像を破棄する
        self.stream.seek(0)
        self.stream.truncate()

        return detect    

    def check_stop(self):
        stop = False
        if cv.waitKey(100) > 0:
            stop = True
        return stop

    def stop_camera(self):

        # 全てのWindowを閉じる
        cv.destroyAllWindows()

if __name__ == '__main__':
    camera = Camera()
    while True:
        if camera.detect_smile():
            print('smile detect')
        if camera.check_stop():
            print('camera stop')
            camera.stop_camera()
            break

実行

コマンドラインから、先程作成した camera.py のディレクトリに移動し、
以下コマンドでプログラムを実行する。

本プログラムでは、
カメラで取得した画像に、
顔の検出結果は「赤色枠」、笑顔の検出結果は「緑色枠」が表示されます。
笑顔の検出は、目(2つ)、鼻、口を検出してそうだったので、
3か所以上検出して初めて「笑顔」と判別するようにしています。

終了するには、画像のWindowをアクティブにした状態で、
何かしらキーを押してください。

python3 camera.py

音声合成

以下記事を参照ください。

Raspberry Pi と Python を使って【天気予報】を喋らせる
今回は、ボタンを押したら、地元の天気予報を喋ってもらおうと思います。楽しそうだったら作ってみて♪この記事では以下が学べます。ボタン制御スピーカー出力PythonWebAPI(外部情報取得)音声合成(発話)やりた...

機能のまとめ

まとめです。
これまで作成した上記機能を組み合わせて、
【笑顔判定機】を作って行きます。

プログラム

この章では、以下赤字のファイルを修正します。
それ以外は、上記ファイルのままで使用します。

/home/pi/work/camera_smile/
├app.py・・・main処理 
├camera.py・・・笑顔判定処理 
└talk.py・・・文字列を音声に変換し、スピーカーから音声出力

app.py

# -*- coding: utf-8 -*-
import camera
import talk

SMILE_JUDGE = 3


if __name__ == '__main__':
    camera = camera.Camera()
    smile_count = 0
    while True:
        if camera.detect_smile():
            print('smile detect')
            smile_count += 1
        else:
            smile_count = 0
        if camera.check_stop():
            print('camera stop')
            camera.stop_camera()
            break
        if smile_count >= SMILE_JUDGE:
            smile_count = 0
            talk.talk(f'おはようございます。今日もいい笑顔ですね。')

実行

コマンドラインから、先程作成した app.py のディレクトリに移動し、
以下コマンドでプログラムを実行する。

本プログラムでは、笑顔判定を3回連続パスしないと
発話してくれません。
SMILE_JUDGEの数を変えることで発話の難易度を変えることが出来ます。

終了するには、画像のWindowをアクティブにした状態で、
何かしらキーを押してください。

最後に

如何だったでしょうか?
いい笑顔は出来ましたか?

他にも、
・物体検知のパラメータを変更したら、検知しやすくなるか、検知しにくくなるか、
・発話内容を変えてみたり、
・発話する箇所をメールを送る処理に変えてみたり、
などなど、色々試してみると楽しいですよ♪

今後も、Raspberry Pi と Python を使ってワクワクするモノを作って行きます。
楽しみにしていてくださいね。

記事を更新するとTwitterでつぶやきます。
あと、下のTwitterアイコンからフォローしてもらうと、
記事を書くモチベーションが上がります♪
フォローお待ちしています。

以下記事では他にも色んな電子工作を作っています。
あなたが作りたいモノのヒントがあれば嬉しいです。

電子工作(Raspberry Pi でできること)
このサイトは、「モノづくりの楽しさをあなたに伝えたい」との思いで作っています。「難易度:☆☆☆」の章に、Raspberry Pi(マイコン) と Python(プログラミング言語)を使ったおもちゃの作り方を書いています。あ...

記事を更新するとTwitterでつぶやきます。
フォローしてもらうと、記事を書くモチベーションが上がります。
下のTwitterアイコンからフォローお願いします。

不明な点があればページTOPの「お問い合わせ」にてご連絡下さい。

もし一人で作るのが難しかったら、
一緒に作るサービスをしています。
お気軽に ページTOPの「お問い合わせ」にてご連絡下さい。

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