はじめに
自社開発している美容診断PWA「lamipas.AI」では、ユーザーがアップロードした写真からMediaPipe Face Meshで468個のランドマークを検出し、8種類の顔診断を行っています。
しかし困った問題があります。MediaPipeは人間以外の顔にもランドマークを無理やりマッピングするのです。猫、犬、アニメキャラ、VTuber、人形——これらすべてに468個のランドマークが生成されます。
そのまま診断エンジンに流すと、おかしな結果が出力されるだけでなく、AI APIのコストも無駄に消費されます。
本記事では、ブレンドシェイプ解析と幾何学的プロポーション検証を組み合わせた2層のバリデーションシステムを紹介します。
アーキテクチャ
写真アップロード
↓
MediaPipe Face Landmarker (numFaces=5)
↓
[基本チェック]
├─ 顔未検出 → エラー
└─ 複数顔 → エラー
↓
[第1層] ブレンドシェイプ検証 ← 主防御
↓
[第2層] ランドマーク幾何学検証 ← バックアップ
↓
診断エンジンへ
第1層: ブレンドシェイプ検証(主防御)
MediaPipeのFace Landmarkerは outputFaceBlendshapes: true を指定すると、51個の表情ブレンドシェイプ(jawOpen, eyeBlink, mouthSmile等)を出力します。
重要な洞察は、この表情モデルは人間専用に訓練されているということです。動物の顔に適用すると、矛盾するパターンが出現します。
矛盾する表情ペアの検出
人間は物理的に、以下の表情を同時に行えません:
const contradictoryPairs: [string, string][] = [
['jawOpen', 'mouthClose'], // 口を開けながら閉じる
['eyeBlinkLeft', 'eyeWideLeft'], // 目を閉じながら見開く
['mouthSmileLeft', 'mouthFrownLeft'], // 笑いながらしかめる
// ... 計7ペア
];
動物の顔に人間の表情モデルを当てると、口のランドマーク配置がマズル(口吻)に引きずられ、「口を開けながら閉じている」という矛盾が発生します。
総表情エネルギーの異常
51個の非neutralブレンドシェイプの合計値(総表情エネルギー)を計算します。
人間が全力で表情を作っても、同時に発火するブレンドシェイプは限られます。しかし動物の顔では、多数が中〜高スコアで同時発火します。
判定基準
if (totalEnergy > 12 || highCount > 6 || contradictions >= 2) {
throw new FaceDetectionError("人間の顔を検出できませんでした");
}
- 総エネルギー > 12: 多数のブレンドシェイプが同時発火
- 高スコア (>0.5) が6個超: 人間は同時に6個以上の強い表情を出せない
- 矛盾ペアが2つ以上: 物理的に不可能な表情の組み合わせ
第2層: ランドマーク幾何学検証(バックアップ)
ブレンドシェイプで検出できないケース(イラスト、2D画像など)に対応するため、ランドマークの位置関係から人間のプロポーションを検証します。
Z深度の平坦さチェック(2D画像検出)
const zValues = zSampleIndices.map((i) => landmarks[i].z);
const zRange = Math.max(...zValues) - Math.min(...zValues);
if (zRange < 0.02) {
throw new FaceDetectionError("イラスト・アニメには対応していません");
}
動物検出スコアリング(9チェックの複合判定)
9つの比率チェックをスコアリングで複合判定し、合計3点以上で非人間と判定します。
なぜ2層にするのか
ブレンドシェイプだけでは不十分な理由:
- イラスト・アニメは表情パターンが人間に近い場合がある
- 静止画では表情エネルギーが低く、閾値を下回ることがある
幾何学だけでは不十分な理由:
- MediaPipeは動物にも人間的なランドマーク配置を生成することがある
- プロポーションが人間の範囲内に収まる動物が存在する
2層を組み合わせることで、異なるシグナルで相互補完し、検出精度を高めています。
iOS Safari での注意点
MediaPipeのGPU delegateはiOS SafariのWebGLでハングします。iOSではCPU delegateを強制しています。
function shouldForceCPU(): boolean {
const ua = navigator.userAgent;
const isIOS =
/iPad|iPhone|iPod/.test(ua) ||
(ua.includes("Macintosh") && navigator.maxTouchPoints > 1);
return isIOS;
}
まとめ
- MediaPipeは人間以外にもランドマークを生成する — バリデーション必須
- 第1層(ブレンドシェイプ): 矛盾する表情パターン + 総エネルギー異常を検出
- 第2層(幾何学): Z深度の平坦さ + 9つのプロポーション比率をスコアリング
- 2層の組み合わせで、動物・アニメ・VTuber・人形・イラストを高精度に弾く
- iOS SafariではGPU delegateを避けCPUを強制する
美容診断サービスに限らず、MediaPipeで顔分析を行うWebアプリケーションでは、入力バリデーションとして同様のアプローチが有効です。