InsightFaceによる68点3Dランドマーク検出
【概要】 InsightFaceフレームワークの68点3Dランドマーク検出技術を用いた顔解析プログラムの実装と実験を行う。68点3Dランドマーク検出は顔の主要な 特徴点を3次元座標で特定する技術である。Webカメラから顔と68点ランドマークを検出する。Windows環境での実行手順、プログラムコード、実験アイデアを含む。

目次
1. はじめに
68点3Dランドマーク検出技術
InsightFaceは顔認識・解析のための統合フレームワークであり、68点3Dランドマーク検出はその中で使用される顔特徴点抽出アルゴリズムの一つである。ランドマーク検出は画像から顔の主要な解剖学的特徴点の位置を特定する技術であり、顔認識、表情解析、3D顔面復元の前段階として使用される。
技術名: 1k3d68(68点3次元顔面ランドマーク検出)
フレームワーク: InsightFace(深層学習ベースの顔解析ツールボックス)
GitHub: https://github.com/deepinsight/insightface
68点3Dランドマーク検出は顔の主要な解剖学的特徴点を3次元座標(x, y, z)で特定することを特徴とする顔解析技術である。Webカメラからの映像をリアルタイムで処理し、顔検出と68点ランドマーク(顎のライン、眉毛、目、鼻、口の詳細な特徴点)の検出を実行する。
68点ランドマークの構成
- 顎のライン(1-17点): 顔の輪郭を定義する点
- 右眉毛(18-22点): 右眉の形状を表現する点
- 左眉毛(23-27点): 左眉の形状を表現する点
- 鼻(28-36点): 鼻梁と鼻先の形状を表現する点
- 右目(37-42点): 右目の輪郭を表現する点
- 左目(43-48点): 左目の輪郭を表現する点
- 口(49-68点): 唇の外側と内側の形状を表現する点
2. Python開発環境,ライブラリ類
Python 3.12 のインストール
インストール済みの場合は実行不要。
管理者権限でコマンドプロンプトを起動(手順:Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)し、以下を実行する。管理者権限は、wingetの--scope machineオプションでシステム全体にソフトウェアをインストールするために必要である。
REM Python をシステム領域にインストール
winget install --scope machine --id Python.Python.3.12 -e --silent
REM Python のパス設定
set "PYTHON_PATH=C:\Program Files\Python312"
set "PYTHON_SCRIPTS_PATH=C:\Program Files\Python312\Scripts"
echo "%PATH%" | find /i "%PYTHON_PATH%" >nul
if errorlevel 1 setx PATH "%PATH%;%PYTHON_PATH%" /M >nul
echo "%PATH%" | find /i "%PYTHON_SCRIPTS_PATH%" >nul
if errorlevel 1 setx PATH "%PATH%;%PYTHON_SCRIPTS_PATH%" /M >nul
【関連する外部ページ】
Python の公式ページ: https://www.python.org/
AI エディタ Windsurf のインストール
Pythonプログラムの編集・実行には、AI エディタの利用を推奨する。ここでは,Windsurfのインストールを説明する。
管理者権限でコマンドプロンプトを起動(手順:Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)し、以下を実行して、Windsurfをシステム全体にインストールする。管理者権限は、wingetの--scope machineオプションでシステム全体にソフトウェアをインストールするために必要となる。
winget install --scope machine Codeium.Windsurf -e --silent
【関連する外部ページ】
Windsurf の公式ページ: https://windsurf.com/
CMakeのインストール
管理者権限でコマンドプロンプトを起動(手順:Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)し、以下を実行する。管理者権限は、wingetの--scope machineオプションでシステム全体にソフトウェアをインストールするために必要となる。
REM CMake をシステム領域にインストール
winget install --scope machine --id Kitware.CMake -e --silent
REM CMake のパス設定
set "GMAKE_PATH=C:\Program Files\CMake\bin"
if exist "%GMAKE_PATH%" (
echo "%PATH%" | find /i "%GMAKE_PATH%" >nul
if errorlevel 1 setx PATH "%PATH%;%GMAKE_PATH%" /M >nul
)
Visual Studio 2022 Build Toolsとランタイムのインストール
管理者権限でコマンドプロンプトを起動(手順:Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)し、以下を実行する。管理者権限は、wingetの--scope machineオプションでシステム全体にソフトウェアをインストールするために必要である。
REM Visual Studio 2022 Build Toolsとランタイムのインストール
winget install --scope machine Microsoft.VisualStudio.2022.BuildTools Microsoft.VCRedist.2015+.x64
set VS_INSTALLER="C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe"
set VS_PATH="C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools"
REM C++開発ワークロードのインストール
%VS_INSTALLER% modify --installPath %VS_PATH% ^
--add Microsoft.VisualStudio.Workload.VCTools ^
--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ^
--add Microsoft.VisualStudio.Component.Windows11SDK.22621 ^
--includeRecommended --quiet --norestart
3. プログラムコード
# InsightFace 68点3Dランドマーク検出プログラム(Webカメラ対応版)
# Webカメラからのリアルタイム顔検出と68点3Dランドマーク抽出
# フレームワーク: InsightFace(深層学習ベースの顔解析ツールボックス)
# GitHub: https://github.com/deepinsight/insightface
# 特徴: 68点3Dランドマーク検出、CNN基盤の深層学習手法(画像認識に特化したニューラルネットワーク)
# 3次元座標系での特徴点検出、顔の詳細な解剖学的構造解析
# 学習済モデル: landmark_3d_68(68点3次元顔面ランドマーク検出モデル)
# 顔の主要な解剖学的特徴点を3次元座標で高精度検出
# 前準備: pip install insightface opencv-python onnxruntime
#
# 利用可能な学習済みモデル:
# - buffalo_l: 大規模モデル、最高精度
# - buffalo_sc: 小規模モデル、高速処理
# - buffalo_s: 小規模モデル、軽量型
# - buffalo_m: 中規模モデル、バランス型
import cv2
import numpy as np
from insightface.app import FaceAnalysis
# 定数定義
CTX_ID = 0
DET_SIZE = (640, 640)
CAMERA_INDEX = 0
FONT_SCALE = 0.6
FONT_COLOR_INFO = (0, 255, 0)
FONT_COLOR_COUNT = (0, 255, 255)
BBOX_COLOR = (255, 0, 0)
LM_COLOR = (0, 255, 0)
LM_RADIUS = 2
# 68点ランドマークの色分け定義
LANDMARK_COLORS = {
'jawline': (255, 0, 0), # 顎のライン (1-17) - 赤
'right_eyebrow': (0, 255, 0), # 右眉毛 (18-22) - 緑
'left_eyebrow': (0, 255, 0), # 左眉毛 (23-27) - 緑
'nose': (255, 255, 0), # 鼻 (28-36) - 黄
'right_eye': (255, 0, 255), # 右目 (37-42) - マゼンタ
'left_eye': (255, 0, 255), # 左目 (43-48) - マゼンタ
'mouth': (0, 255, 255) # 口 (49-68) - シアン
}
print("InsightFace 68点3Dランドマーク検出プログラムを開始します")
print("landmark_3d_68(68点3次元顔面ランドマーク検出)")
print("終了するには 'q' キーを押してください")
# 顔解析用アプリケーション初期化(68点3Dランドマーク検出を有効化)
app = FaceAnalysis(name='buffalo_l', allowed_modules=['detection', 'landmark_3d_68'])
app.prepare(ctx_id=CTX_ID, det_size=DET_SIZE)
print("68点3Dランドマーク検出モデル(1k3d68)をロードしました")
# カメラ初期化(DirectShowバックエンド使用)
cap = cv2.VideoCapture(CAMERA_INDEX, cv2.CAP_DSHOW)
if not cap.isOpened():
print(f"カメラ {CAMERA_INDEX} のオープンに失敗しました")
print("プログラムを終了します")
exit(1)
# バッファサイズを1に設定してリアルタイム性を向上
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
print(f"カメラ {CAMERA_INDEX} を初期化しました")
frame_count = 0
def get_landmark_color(landmark_idx):
"""ランドマークインデックスに応じた色を返す"""
if 1 <= landmark_idx <= 17:
return LANDMARK_COLORS['jawline']
elif 18 <= landmark_idx <= 22:
return LANDMARK_COLORS['right_eyebrow']
elif 23 <= landmark_idx <= 27:
return LANDMARK_COLORS['left_eyebrow']
elif 28 <= landmark_idx <= 36:
return LANDMARK_COLORS['nose']
elif 37 <= landmark_idx <= 42:
return LANDMARK_COLORS['right_eye']
elif 43 <= landmark_idx <= 48:
return LANDMARK_COLORS['left_eye']
elif 49 <= landmark_idx <= 68:
return LANDMARK_COLORS['mouth']
else:
return LM_COLOR
# メイン処理
while True:
# バッファをクリア(最新フレームのみ取得)
cap.grab()
ret, frame = cap.retrieve()
if not ret:
break
frame_count += 1
# 顔検出・ランドマーク検出実行
faces = app.get(frame)
# 検出結果の描画とコンソール出力
for face_idx, face in enumerate(faces):
# 境界ボックス描画
bbox = face.bbox.astype(int)
cv2.rectangle(frame, (bbox[0], bbox[1]), (bbox[2], bbox[3]), BBOX_COLOR, 2)
# 検出信頼度表示
confidence = face.det_score if hasattr(face, 'det_score') else 0.0
conf_text = f"Conf: {confidence:.3f}"
cv2.putText(frame, conf_text, (bbox[0], bbox[1] - 5),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, BBOX_COLOR, 1)
# 68点3Dランドマーク検出処理
landmarks_detected = False
landmark_count = 0
landmarks = None
# landmark_3d_68属性を確認
if hasattr(face, 'landmark_3d_68') and face.landmark_3d_68 is not None:
landmarks = face.landmark_3d_68
landmarks_detected = True
landmark_count = len(landmarks)
print(f"Using landmark_3d_68 with {landmark_count} points")
if landmarks_detected and landmarks is not None:
print(f"\n=== Face {face_idx + 1} (Frame {frame_count}) ===")
print(f"Detection Confidence: {confidence:.4f}")
print(f"Total Landmarks: {landmark_count}")
print("Landmark Details (ID, X, Y, Z):")
# 各ランドマークを色分けして描画・出力
for i, landmark in enumerate(landmarks):
if len(landmark) >= 2:
x, y = int(landmark[0]), int(landmark[1])
z = landmark[2] if len(landmark) > 2 else 0.0
# 68点用の色分け
color = get_landmark_color(i + 1)
cv2.circle(frame, (x, y), LM_RADIUS, color, -1)
# コンソール出力(最初の20点のみ)
if i < 20:
print(f" {i+1:2d}: ({x:3d}, {y:3d}, {z:6.2f})")
elif i == 20:
print(f" ... (残り{landmark_count - 20}点は省略) ...")
# ランドマーク番号表示
if frame_count % 30 == 0:
cv2.putText(frame, str(i + 1), (x + 3, y - 3),
cv2.FONT_HERSHEY_SIMPLEX, 0.3, color, 1)
else:
print(f"\n=== Face {face_idx + 1} (Frame {frame_count}) ===")
print(f"Detection Confidence: {confidence:.4f}")
print("Landmarks: landmark_3d_68 not detected")
# フレーム情報表示
info_text = f"Frame: {frame_count} | 68-Point 3D Landmark Detection"
cv2.putText(frame, info_text, (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, FONT_SCALE, FONT_COLOR_INFO, 2)
# 検出された顔の数を表示
face_count_text = f"Detected faces: {len(faces)}"
cv2.putText(frame, face_count_text, (10, 60),
cv2.FONT_HERSHEY_SIMPLEX, FONT_SCALE, FONT_COLOR_COUNT, 2)
# ランドマーク点数を表示
total_landmarks = 0
for face in faces:
if hasattr(face, 'landmark_3d_68') and face.landmark_3d_68 is not None:
total_landmarks += len(face.landmark_3d_68)
break
landmark_text = f"Total landmarks: {total_landmarks}"
cv2.putText(frame, landmark_text, (10, 90),
cv2.FONT_HERSHEY_SIMPLEX, FONT_SCALE, FONT_COLOR_COUNT, 2)
# 色分け凡例表示
legend_y = 120
legend_items = [
("Jawline", LANDMARK_COLORS['jawline']),
("Eyebrows", LANDMARK_COLORS['right_eyebrow']),
("Nose", LANDMARK_COLORS['nose']),
("Eyes", LANDMARK_COLORS['right_eye']),
("Mouth", LANDMARK_COLORS['mouth'])
]
for i, (label, color) in enumerate(legend_items):
y_pos = legend_y + i * 25
cv2.circle(frame, (15, y_pos), 5, color, -1)
cv2.putText(frame, label, (30, y_pos + 5),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1)
# 結果出力
cv2.imshow("InsightFace 68-Point 3D Landmark Detection", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 終了処理
cap.release()
cv2.destroyAllWindows()
print("プログラムを終了しました")
4. 使用方法
- 上記のプログラムを実行する
- Webカメラの映像が表示され、検出された顔に赤色の境界ボックスと色分けされた68点ランドマークが表示される。
- ランドマークは以下のように色分けされる:
- 顎のライン(1-17点): 赤色
- 眉毛(18-27点): 緑色
- 鼻(28-36点): 黄色
- 目(37-48点): マゼンタ色
- 口(49-68点): シアン色
- 各顔の上部に検出信頼度(0.000~1.000)が表示される。検出信頼度は0.0から1.0の値で、1.0に近いほど顔である確信度が高い。0.5以上を閾値として使用することが多い。
- 画面左側に色分け凡例が表示される。
- 'q'キーを押すとプログラムが終了する。
5. 実験・探求のアイデア
AIモデル選択による比較実験
プログラム内のname='buffalo_sc'
を以下のモデルに変更して、性能の違いを確認する。
buffalo_l
: 最高精度、処理速度は低いbuffalo_m
: 中規模、バランス型buffalo_s
: 軽量で高速buffalo_sc
: 小規模、高速処理
検出サイズの変更実験
DET_SIZE = (640, 640)
の値を変更して、検出精度と処理速度への影響を確認する。
- (320, 320): 高速処理、小さい顔の検出が困難
- (1280, 1280): 高精度、処理速度が低下
様々な条件での検出性能テスト
- 複数人の同時検出
- 横顔や斜め顔での検出精度
- マスク着用時の検出性能
- 暗い環境での検出限界
- 手で顔の一部を隠した場合の挙動
- 表情変化によるランドマーク位置の変動解析
68点ランドマーク活用の探求
検出された68点ランドマークの座標を利用して、以下の解析を実行する:
- 頭部姿勢推定: 鼻尖と目の位置関係から頭部の向きを計算
- 表情認識: 口角と眉毛の位置変化から基本表情を判定
- 目の開閉検出: 目のランドマーク(37-48点)から目のアスペクト比(EAR)を計算
- 口の動き解析: 口のランドマーク(49-68点)から口のアスペクト比(MAR)を計算
- 顔の対称性解析: 左右のランドマーク位置から顔の対称性を評価
- 3D顔面形状復元: 68点の3次元座標から顔面メッシュを構築
ランドマーク精度評価実験
- 異なる照明条件下での検出精度比較
- 顔の角度変化に対するランドマーク安定性評価