先週に引き続き、InsightFaceでの顔認識に取り組みました。今回は、事前に環境構築を終えていた学生さんたちと一緒に、静止画での顔検出からリアルタイム処理、さらに特徴量を使った顔認証に関するステップを少しずつ進めてみました。以下、授業で扱ったコードやポイントをまとめていますので、興味のある方はぜひ試してみてください。
1. 実行環境の準備
(1) Microsoft C++ Build Toolsのインストール(Windowsユーザー向け)
Pythonの一部パッケージをビルドするときに必要となるため、まだの方は以下から入手してインストールしておきましょう。
Microsoft C++ Build Tools
vs_BuildTools.exe を実行し、「C++によるデスクトップ開発」をチェックしてインストール
多少時間がかかりますが、気長にお待ちください。
(2) 必要ライブラリのインストール
Python 3.x 環境で、仮想環境を作ったあと以下のコマンドを実行してライブラリをインストールします。
pip install onnxruntime
pip install insightface opencv-python matplotlib
onnxruntime : モデルの推論を高速化するために使用
insightface : メインの顔検出・顔認証ライブラリ
opencv-python : 画像の読み込みや表示、矩形描画などに使用
matplotlib : 検出結果を可視化するために使用
2. InsightFaceを使った顔検出(静止画編)
まずは、InsightFaceで顔検出を行うためのベーシックなコードを見てみましょう。下記のプログラムでは、カメラアプリなどで撮影した画像(sample.jpg)から顔を検出し、その領域を枠で囲むようになっています。
from insightface.app import FaceAnalysis
import cv2
# 1. InsightFaceのセットアップ
app = FaceAnalysis()
app.prepare(ctx_id=0, det_size=(640, 640))
# 2. サンプル画像のロード
img_path = "sample.jpg" # 画像ファイルを用意
img = cv2.imread(img_path)
# 3. 顔検出
faces = app.get(img)
print(f"Detected {len(faces)} face(s).")
# 4. 検出結果の表示
for face in faces:
box = face.bbox.astype(int)
cv2.rectangle(img, (box[0], box[1]), (box[2], box[3]), (0, 255, 0), 2)
cv2.imshow("Faces", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
faces の中には、顔の領域 (bbox) やスコア (det_score)、さらにキーポイントなどの情報が含まれています。
複数の顔が映っている画像では、同時に複数個の矩形が描画されるはずです。
3. リアルタイム顔検出(Webカメラ編)
静止画での検出に慣れたら、次はリアルタイム処理に挑戦です。以下のポイントに気をつけながら実装するとスムーズに進められます。
OpenCVの VideoCapture を利用してカメラ映像を取得する
取得した各フレームに対して InsightFaceで顔検出 を行う
結果を画面に表示しながら、ループを継続する
例えば、下記のようなコード例で実装できます。
from insightface.app import FaceAnalysis
import cv2
# 1. InsightFaceのセットアップ
app = FaceAnalysis()
app.prepare(ctx_id=0, det_size=(640, 640))
# 2. カメラのセットアップ
cap = cv2.VideoCapture(0) # カメラデバイスのインデックス(通常は0)
if not cap.isOpened():
print("Error: カメラが見つかりません。")
exit()
print("カメラが起動しました。'q'キーで終了します。")
# 3. リアルタイム映像の処理
while True:
ret, frame = cap.read()
if not ret:
print("Error: フレームを読み込めませんでした。")
break
# 顔検出
faces = app.get(frame)
for face in faces:
box = face.bbox.astype(int)
cv2.rectangle(frame, (box[0], box[1]), (box[2], box[3]), (0, 255, 0), 2)
# 映像を表示
cv2.imshow("Real-Time Face Detection", frame)
# 'q'キーで終了
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 4. リソースの解放
cap.release()
cv2.destroyAllWindows()
実行すると、カメラに写った人の顔が四角で囲まれるはずです。複数の顔が映ったら、同時に複数検出されるかどうかもチェックしてみましょう。
また、顔の年齢推定や性別推定をオーバーレイ表示してみるのも面白いです。
import cv2
from insightface.app import FaceAnalysis
# InsightFaceのセットアップ
app = FaceAnalysis()
app.prepare(ctx_id=0, det_size=(640, 640))
# カメラのセットアップ
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Error: カメラが起動できませんでした。")
exit()
print("カメラが起動しました。'q'キーを押して終了してください。")
while True:
ret, frame = cap.read()
if not ret:
print("Error: フレームが取得できませんでした。")
break
# 顔検出と年齢・性別推定
faces = app.get(frame)
for face in faces:
box = face.bbox.astype(int)
cv2.rectangle(frame, (box[0], box[1]), (box[2], box[3]), (0, 255, 0), 2)
# 年齢と性別の情報を取得
gender = "Male" if face.gender == 1 else "Female"
age = int(face.age)
label = f"{gender}, {age} years"
cv2.putText(frame, label, (box[0], box[1] - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 2)
cv2.imshow("Real-Time Age and Gender Prediction", frame)
# 'q'キーで終了
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
4. 顔検出結果を利用した画像加工
InsightFaceを使って取得した顔の位置情報をもとに、以下のような加工が可能です。
(1) モザイク処理
検出した顔の領域をモザイク化できます。顔だけを隠したい場合などに便利です。
import cv2
from insightface.app import FaceAnalysis
# InsightFaceのセットアップ
app = FaceAnalysis()
app.prepare(ctx_id=0, det_size=(640, 640))
# 画像の読み込み
img_path = "sample.jpg"
img = cv2.imread(img_path)
# 顔検出
faces = app.get(img)
# 顔領域にモザイクをかける
for face in faces:
box = face.bbox.astype(int)
x1, y1, x2, y2 = box
face_region = img[y1:y2, x1:x2]
face_region = cv2.GaussianBlur(face_region, (23, 23), 30) # モザイク処理
img[y1:y2, x1:x2] = face_region
cv2.imshow("Processed Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
(2) スタンプやエフェクトの追加
検出した**顔パーツ(目や口)**に合わせてスタンプやフィルターを重ねられます。
import cv2
from insightface.app import FaceAnalysis
import numpy as np
# InsightFaceのセットアップ
app = FaceAnalysis()
app.prepare(ctx_id=0, det_size=(640, 640))
# 画像の読み込み
img_path = "sample2.jpg"
img = cv2.imread(img_path)
if img is None:
raise FileNotFoundError(f"画像が見つかりません: {img_path}")
# スタンプ画像の読み込み (アルファチャンネル必須: RGBA形式)
stamp_path = "stamp.png"
stamp = cv2.imread(stamp_path, cv2.IMREAD_UNCHANGED)
if stamp is None:
raise FileNotFoundError(f"スタンプ画像が見つかりません: {stamp_path}")
if stamp.shape[2] != 4:
raise ValueError("スタンプ画像にアルファチャンネルがありません。")
# 顔検出とランドマークの取得
faces = app.get(img)
if not faces:
print("顔が検出されませんでした。")
else:
for face in faces:
keypoints = face.kps.astype(int)
print("主要ランドマーク:", keypoints)
# 両目の中心を計算し、そこを基準にスタンプを配置
left_eye, right_eye = keypoints[0], keypoints[1]
center_x = (left_eye[0] + right_eye[0]) // 2
center_y = (left_eye[1] + right_eye[1]) // 2
# 顔の幅に応じてスタンプをリサイズ
bbox = face.bbox.astype(int)
face_width = bbox[2] - bbox[0]
scale_factor = 1.5
new_width = int(face_width * scale_factor)
new_height = int(stamp.shape[0] * (new_width / stamp.shape[1]))
stamp_resized = cv2.resize(stamp, (new_width, new_height),
interpolation=cv2.INTER_AREA)
h, w, _ = stamp_resized.shape
x1, y1 = max(0, center_x - w // 2), max(0, center_y - h // 2)
x2, y2 = min(img.shape[1], x1 + w), min(img.shape[0], y1 + h)
stamp_cropped = stamp_resized[0 : y2 - y1, 0 : x2 - x1]
overlay = img[y1:y2, x1:x2]
stamp_rgb = stamp_cropped[:, :, :3]
alpha = stamp_cropped[:, :, 3] / 255.0
# アルファブレンディング
for c in range(3):
overlay[:, :, c] = alpha * stamp_rgb[:, :, c] + \
(1 - alpha) * overlay[:, :, c]
img[y1:y2, x1:x2] = overlay
cv2.imshow("Processed Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
次回予告
次回は、
自分の顔の特徴量をデータベース化する
データベース化した特徴量を使用した顔認証(静止画)
リアルタイム顔認証
に取り組んでみたいと思います。ここまでの知識を活かして、より高度な顔認識アプリケーションを作ることが可能になりますので、ぜひお楽しみに!
コメント