【ルネサス技術コラム】Raspberry Pi 5で動かす簡易「笑顔チェック」Webアプリ
Raspberry Pi 5で動かす簡易「笑顔チェック」Webアプリを作ってみた
受付端末やセルフ撮影ブース、会員登録の顔写真確認、プレゼン練習などでは、「今この人が笑顔っぽい状態か」をその場で手軽に表示したい場面があります。そこで今回も、「エレクトロニクスを簡単に」をテーマに、Raspberry Pi 5に接続したUSBカメラ映像を使って笑顔らしさを簡易表示し、同一ネットワーク内のPCブラウザから確認できるWebアプリを、できるだけ短いプログラムで試作してみました。
Raspberry Pi
今回の構成は、人物識別や感情推定ではなく、固定カメラ前提で顔と口元を簡易検出し、笑顔っぽい状態を可視化するPoCに絞っています。この割り切りによって、PoCとして扱いやすく、追加のモデルランタイムにも依存しにくい構成にできます。
実行環境には Raspberry Pi 5を想定しています。Raspberry Pi 5 は Raspberry Pi 公式でも高性能な汎用コンピュータとして案内されており、Raspberry Pi OS と組み合わせることで、軽量なカメラPoCやローカルWebアプリを載せやすいです。Raspberry Pi 5は従来世代比で2~3倍の性能向上が案内されており、USBカメラ入力と軽量な画像処理を同時に動かす用途でも扱いやすいです。
今回使うのは Flask と OpenCVです。顔検出と笑顔検出には OpenCVの CascadeClassifier を使い、公式リポジトリにも含まれている haarcascade_frontalface_default.xml と haarcascade_smile.xml を利用します。OpenCV 4.5.0以降は Apache 2.0 ライセンスで提供されています。
目次
はじめに
今回のアプリは、Raspberry Pi 5にUSBカメラを接続して固定設置し、そのライブ映像の中から顔を見つけ、口元に笑顔らしい特徴が見つかったら状態表示を切り替える仕組みです。映像処理自体は Raspberry Pi 5側で行い、確認用の画面は同一ネットワーク内のPCブラウザから開く構成にしています。
構成としてはとてもシンプルで、
Raspberry Pi 5にUSBカメラを接続する
カメラ映像を Raspberry Pi 5側で読み込む
顔を検出する
顔領域の下半分を中心に笑顔らしい口元パターンを検出する
SMILE OK / KEEP SMILING / NO FACE を表示する
同一ネットワーク内のPCブラウザで結果を見る
という流れだけに絞っています。
OpenCVのCascade Classifierを選んだ理由
今回は大規模なAIモデルを利用せず、Raspberry Pi単体で手軽に試せることを重視して Haar Cascade を採用しました。
Webアプリの基本構成
今回は Flask ベースのWebアプリとして実装し、ブラウザにはMJPEG ストリームとしてUSBカメラ映像を表示します。Flask では generator を使ったストリーミングレスポンスのパターンが公式ドキュメントで説明されており、継続的にフレームを返す構成を作れます。
Flask Streaming
カメラ入力は OpenCVの VideoCapture を使います。OpenCVのドキュメントでも、VideoCapture はカメラ・動画ファイル・画像列から映像を取得するためのクラスとして説明されています。Raspberry Pi 5 に接続したUSBカメラをここで開き、そのフレームを逐次処理して返すだけでも、PoCとしては十分動く構成にできます。
OpenCV VideoCapture
また、今回は Raspberry Pi 5上でFlask を 0.0.0.0 バインドで起動し、同一ネットワーク内のPCから http://RaspberryPiのIPアドレス:5000 にアクセスする構成を取ります。これにより、処理はPi側、確認はPC側という役割分担にできます。
今回の処理フローは以下の通りです。
Raspberry Pi 5でUSBカメラを起動
各フレームをグレースケール化
顔を検出
顔領域の下半分で笑顔を検出
検出結果に応じてSMILE OK / KEEP SMILING / NO FACE を表示
同一ネットワーク内のPCブラウザに映像を表示
ディレクトリ構成
smile-check-pi5-app/
├── app.py
└── requirements.txtサンプルコード
今回はできるだけ短くするために、HTML も Python 側へ埋め込んだ1ファイル構成にしています。
Raspberry Pi 5にUSBカメラを接続して起動すると、同一ネットワーク内のPCブラウザから映像を見ながら、笑顔らしい状態かどうかを簡易表示できます。
※本サンプルコードは生成AIを活用して作成して、動作確認を行っています。
python
import cv2
from flask import Flask, Response
app = Flask(__name__)
face_cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
)
smile_cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + "haarcascade_smile.xml"
)
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
def gen_frames():
while True:
ok, frame = cap.read()
if not ok or frame is None:
continue
frame = cv2.flip(frame, 1)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(80, 80)
)
status = "NO FACE"
color = (120, 120, 120)
for (x, y, w, h) in faces[:1]:
roi_gray = gray[y:y + h, x:x + w]
mouth_gray = roi_gray[h // 2:h, :]
smiles = smile_cascade.detectMultiScale(
mouth_gray,
scaleFactor=1.7,
minNeighbors=20,
minSize=(25, 25)
)
if len(smiles) > 0:
status = "SMILE OK"
color = (0, 200, 0)
else:
status = "KEEP SMILING"
color = (0, 170, 255)
cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
for (sx, sy, sw, sh) in smiles[:1]:
cv2.rectangle(
frame,
(x + sx, y + h // 2 + sy),
(x + sx + sw, y + h // 2 + sy + sh),
color,
2
)
break
cv2.putText(
frame, status, (20, 40),
cv2.FONT_HERSHEY_SIMPLEX, 1.0, color, 3, cv2.LINE_AA
)
ret, buffer = cv2.imencode(".jpg", frame, [cv2.IMWRITE_JPEG_QUALITY, 85])
if not ret:
continue
yield (
b"--frame\r\n"
b"Content-Type: image/jpeg\r\n\r\n" +
buffer.tobytes() +
b"\r\n"
)
@app.route("/")
def index():
return """<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Raspberry Pi 5 笑顔チェックアプリ</title>
<style>
body { font-family: system-ui, sans-serif; background:#f6f7fb; margin:0; padding:24px; color:#222; }
.wrap { max-width:980px; margin:auto; background:#fff; border-radius: 16px; padding: 24px; box-shadow: 0 4px 20px rgba(0,0,0,0.08); }
h1 { margin-top:0; }
.card { margin:16px 0; padding: 16px; border:1px solid #e5e7eb; border-radius: 12px; background:#fafafa; }
img { width: 100%; max-width: 900px; border-radius: 12px; border:1px solid #ddd; display:block; }
.muted { color: #555; font-size:14px; }
</style>
</head>
<body>
<div class="wrap">
<h1>Raspberry Pi 5 笑顔チェックアプリ</h1>
<p>USBカメラ映像から笑顔らしい状態を簡易表示し、同一ネットワーク内のPCブラウザから確認します。</p>
<div class="card">
<p class="muted">※ このPoCは人物識別や感情断定ではなく、顔と口元の簡易検出によるデモです。</p>
</div>
<div class="card">
<h3>USBカメラ映像</h3>
<img src="/video_feed" alt="camera stream">
</div>
</div>
</body>
</html>"""
@app.route("/video_feed")
def video_feed():
return Response(
gen_frames(),
mimetype="multipart/x-mixed-replace; boundary=frame"
)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=False)requirements.txt
Flask>=3.1,<4
opencv-python-headless>=4.10,<5セットアップ手順
まずは Raspberry Pi 5 に Raspberry Pi OS を入れて起動しておきます。Raspberry Pi 公式でも、Raspberry Pi OS は公式サポートOSとして案内されています。
Raspberry Pi OS
その後、Raspberry Pi 5上で仮想環境を作り、依存ライブラリをインストールします。
bash
mkdir smile-check-pi5-app
cd smile-check-pi5-app
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip setuptools wheel
python -m pip install -r requirements.txt今回は OpenCVの Haar Cascade XMLを cv2.data.haarcascades から参照するため、追加のモデルファイルを別途ダウンロードしなくても動かしやすい構成です。OpenCVの公式リポジトリには顔用・笑顔用を含む複数の cascade XML が含まれています。
OpenCV Haar Cascades
app.py を保存したら、以下で起動します。
bash
python app.py同一ネットワーク内のPCブラウザから以下へアクセスします。
http://RaspberryPiのIPアドレス:5000
使い方
操作は以下の流れです。
Raspberry Pi 5にUSBカメラを接続する
カメラが顔を正面から見やすい位置に固定されていることを確認する
Raspberry Pi 5上でアプリを起動する
同一ネットワーク内のPCブラウザからアクセスする
顔が映ると、笑顔らしい口元が見つかった場合に SMILE OK と表示される
顔はあるが笑顔検出が無い場合は KEEP SMILING と表示される
顔が映っていない場合は NO FACE と表示される
このサンプルでは、最も主要な1人の顔だけを対象にし、笑顔らしさの目安を単純表示する構成にしています。複数人の同時判定や感情分類は、あえて外して短いコードにしています。
実装のポイント
今回の実装は、表情チェックの流れをなるべくストレートに書いています。まず顔全体を検出し、その顔領域の下半分を口元候補として切り出し、そこで笑顔検出をかけています。顔全体に直接 smile cascade をかけるよりも、対象範囲を絞ったほうがPoCとしては扱いやすいです。
また、ライブ映像のブラウザ表示は Flask のストリーミングレスポンスで実現しています。Flask 公式ドキュメントでは generator で逐次データを返す方法が説明されており、この方式を使うとMJPEGのような単純なライブ表示を作りやすいです。
Flask Streaming
カメラ入力には OpenCVの VideoCapture を使っています。これはカメラデバイスを開いてフレームを読むための標準的なクラスで、Raspberry Pi 5に接続したUSBカメラを扱うPoCとしてもシンプルです。
OpenCV VideoCapture
さらに、今回使っている Cascade Classifier は OpenCVの基本的な物体検出機能のひとつです。事前に用意された分類器ファイルを読み込んで矩形検出する仕組みなので、重い推論ランタイムを使わずにPoCを組みやすいのが利点です。
OpenCV Documentation
注意点
このサンプルは「笑顔を感情として判定する」アプリではなく、「笑顔らしい口元パターンを簡易検出する」 最小構成です。そのため、実運用を考えるといくつか注意点があります。
まず、この構成は感情そのものを正確に推定しているわけではありません。口元の形状パターンに近いものを拾っているだけなので、発話中、あくび、口元の影、歯の見え方などで反応する可能性があります。逆に、控えめな笑顔や顔の角度によっては検出しにくい場合もあります。
また、精度は撮影条件に強く影響されます。逆光、強い影、横顔、マスク、解像度不足、カメラの高さのズレなどでは、顔検出や笑顔検出が安定しにくくなります。PoCの段階では十分でも、実環境では scaleFactor、minNeighbors、minSize の調整が必要です。
Raspberry Pi 5 は高性能な部類ですが、それでもエッジ側で連続映像処理を行う以上、解像度やフレームレートを上げすぎると負荷が増えます。PoCの段階では640×480程度から試し、必要に応じて画質と負荷のバランスを見るほうが扱いやすいです。
Raspberry Pi
最後に、顔画像を扱う用途では、利用場所や運用方法に応じたプライバシー配慮も必要です。今回の構成はローカル処理の簡易PoCですが、実運用前には保存の有無、利用目的、表示方法などを整理しておくほうが安全です。
今後の改善案
今回のサンプルは最小構成なので、今後は以下のような拡張が考えられます。
複数人対応にする
最初の1人だけでなく、検出した複数の顔に対して個別に表示するようにすると、イベント受付などでも使いやすくなります。笑顔の強さを段階表示する
単純なOK/NGだけでなく、笑顔検出の回数や口元矩形の安定度を使って3段階程度に分けると、デモとして見やすくなります。撮影品質チェックに広げる
顔の大きさ、中央寄りかどうか、明るさなども合わせれば、受付写真や会員登録写真の簡易撮影OK判定にも広げやすいです。CSVログ保存を追加する
一定時間ごとの笑顔検出回数を残しておくと、デモ評価や改善検討に使いやすくなります。systemd で自動起動する
Raspberry Pi 5の電源投入後にアプリを自動で立ち上げるようにすると、現場設置がしやすくなります。
関連技術参考トピック
今回は Raspberry Pi 5を用いた簡易PoCとして実装しましたが、実際に受付端末や店舗端末、セルフ撮影機器などへ展開する場合には、AIアクセラレータを搭載した Renesas RZ/V シリーズも有力な選択肢になります。RZ/Vシリーズは画像認識や人物検出などのエッジAI用途を想定しており、カメラ入力を活用した組込み機器開発への展開も検討できます。
・RZ/V Embedded AI MPU
まとめ
今回は、Raspberry Pi 5上で動く簡易「笑顔チェック」 Webアプリを作ってみました。USBカメラ映像から顔を検出し、口元の特徴をもとに笑顔らしい状態を簡易表示することで、受付端末やセルフ撮影ブース、プレゼン練習などで活用できるPoCを手軽に試せる構成です。
構成自体はシンプルですが、
USBカメラ映像をリアルタイムで取得する
顔領域を検出する
笑顔らしい口元パターンを簡易検出する
Webブラウザから結果を確認する
ローカル環境で完結しやすい
という流れを通して、画像処理やエッジAIアプリケーションの入り口として扱いやすい題材になりました。
今回は OpenCVのHaar Cascade を用いた最小構成としましたが、今後は複数人対応や撮影品質チェック、より高度な画像認識機能の追加などへ発展させることもできます。また、PoCから実運用・組込み機器への展開を検討する際には、RenesasのRZ/VシリーズのようなAI処理に対応したMPUを活用することで、より本格的なエッジAIソリューションへ発展させることも期待できます。
「エレクトロニクスを簡単に」の観点職でも、まずは身近なRaspberry PiとOSSを活用して小さく試し、そこから実用的な画像認識アプリケーションへ発展させていく第一歩として楽しめるテーマではないでしょうか。
参考リンク
・Raspberry Pi 5
・Raspberry Pi Software / Raspberry Pi OS
・OpenCV License
・OpenCV CascadeClassifier
・OpenCV VideoCapture
・OpenCV Haar Cascades
・Flask: Streaming Contents
・RZ/V Embedded AI MPU





