Insight Face 教科書

【概要】InsightFaceは、オープンソースの2D&3D顔解析フレームワーク。顔検出(RetinaFace・SCRFD),顔認識(ArcFace)の機能を持つ。512次元の特徴ベクトルで顔を数値化してコサイン類似度により類似判定を行う。

目次

第1章 序論

1.1 顔解析技術の歴史的背景と社会的意義

顔解析技術は、1960年代の初期パターン認識研究から始まり、現代のディープラーニング技術によって大きな発展を遂げた。特に2010年代以降、畳み込みニューラルネットワーク(CNN)の発達により、高い精度を実現している。

現代社会において顔解析技術は、セキュリティシステム、個人認証、感情分析、人口統計分析など幅広い分野で活用されている。特に非接触型の生体認証として、COVID-19パンデミック以降、その活用が拡大している。

1.2 InsightFaceの概要

InsightFaceは、オープンソースの顔解析フレームワークである。学術的貢献として、顔検出のSCRFD(ICLR 2022採択)およびRetinaFace(CVPR 2020採択)と顔認識のArcFace(CVPR 2019採択)を開発している。

ライセンス情報:

必要な前提知識:

第2章 顔解析の技術基盤

2.1 特徴ベクトルと類似度計算

特徴ベクトルとは、顔画像の特徴を数値化した多次元ベクトルである。InsightFaceでは512次元のベクトルとして表現される。

コサイン類似度は、2つのベクトル間の類似性を測定する指標である:

cos(θ) = (A・B) / (|A| × |B|)

ここで、A・Bは内積、|A|、|B|はそれぞれのベクトルのノルムを表す。値域は[-1, 1]で、1に近いほど類似度が高くなる。

2.2 深層学習における顔認識の仕組み

顔認識では、CNNを用いて顔画像から特徴ベクトルを抽出する。学習過程では、同一人物の顔は近い特徴ベクトルに、異なる人物の顔は遠い特徴ベクトルになるように最適化される。

2.3 顔検出と顔認識の違い

必要な前提知識:

2.4 損失関数と角度マージンの理論

必要な前提知識:

2.5 モデル形式とONNXの基礎

必要な前提知識:

第3章 InsightFaceの技術詳細

3.1 顔検出技術(RetinaFace・SCRFD)

InsightFaceでは、モデルパックに応じて2つの顔検出技術を使用している:

RetinaFace(buffalo系で使用)

SCRFD(antelopev2で使用)

計算量による性能階層

3.2 ArcFace顔認識技術

ArcFaceは、InsightFaceが開発した角度マージン損失による顔認識手法である(CVPR 2019採択)。

学習データセットによる性能差

アプリケーションの要求に応じてモデルを選択できる。リアルタイム処理が必要な場合はbuffalo_m、最高精度が必要な場合はantelopev2が適用される。

3.3 処理パイプライン

InsightFaceの顔解析処理は以下の順序で実行される:

[入力画像]
    ↓
[1. 顔検出(RetinaFace/SCRFD)] → 境界ボックス検出
    ↓
[2. 顔ランドマーク検出] → 特徴点位置特定
    ↓
[3. 顔認識(ArcFace)] → 特徴ベクトル抽出
    ↓
[4. 属性推定] → 年齢・性別推定
    ↓
[出力結果]

3.4 モデルパック構成

InsightFaceでは以下のモデルパックを提供している:

buffalo系(buffalo_l, buffalo_m, buffalo_s, buffalo_sc)に含まれる5つのONNXファイル:

antelopev2に含まれる5つのONNXファイル:

第4章 環境構築と基本実装

4.1 環境構築と基本設定

目的:InsightFaceの基本的なセットアップを行う
期待される結果:顔解析機能が使用可能な状態になる

import insightface
from insightface.app import FaceAnalysis

# 最高精度(antelopev2使用)
app = FaceAnalysis(name='antelopev2', providers=['CUDAExecutionProvider', 'CPUExecutionProvider'])
app.prepare(ctx_id=0, det_size=(640, 640))

4.1.1 ランドマークモデルの指定方法

InsightFaceではallowed_modulesパラメータを使用して、使用するモジュールを指定できる:

# 1. すべてのモジュールを使用(デフォルト)
app = FaceAnalysis()

# 2. 特定のモジュールのみを使用
app = FaceAnalysis(allowed_modules=['detection', 'recognition'])

# 3. 2D 106点ランドマークのみを使用
app = FaceAnalysis(allowed_modules=['detection', 'landmark_2d_106'])

# 4. 3D 68点ランドマークのみを使用
app = FaceAnalysis(allowed_modules=['detection', 'landmark_3d_68'])

# 5. 両方のランドマークを使用
app = FaceAnalysis(allowed_modules=['detection', 'landmark_2d_106', 'landmark_3d_68'])

# 6. 顔検出のみ
app = FaceAnalysis(allowed_modules=['detection'])

指定可能なモジュール:

4.2 基本的な顔検出

目的:画像から顔を検出し、基本情報を取得する
期待される結果:検出された顔の数、位置、キーポイントが出力される


# InsightFace顔検出プログラム
#   静的画像からの顔検出とキーポイント抽出
#   論文: "RetinaFace: Single-Shot Multi-Level Face Localisation in the Wild" (CVPR 2020)
#   GitHub: https://github.com/deepinsight/insightface
#   特徴: RetinaFaceアルゴリズムによる高精度顔検出、CNN基盤の深層学習手法
#         マルチスケール検出対応、顔境界ボックスと5点キーポイント同時検出
#   学習済モデル: SCRFD(Sample and Computation Redistributed Face Detection)
#                 軽量化と高精度を両立した顔検出モデル
#   前準備: pip install insightface opencv-python onnxruntime

import cv2
from insightface import FaceAnalysis
from insightface.data import get_image as ins_get_image

# 定数定義
CTX_ID = 0
DET_SIZE = (640, 640)
TEST_IMAGE = 't1'

# 顔検出用アプリケーション初期化
app = FaceAnalysis(allowed_modules=['detection'])
app.prepare(ctx_id=CTX_ID, det_size=DET_SIZE)

# テスト画像読み込み
img = ins_get_image(TEST_IMAGE)

# メイン処理
faces = app.get(img)

# 結果出力
print(f"検出された顔の数: {len(faces)}")

for i, face in enumerate(faces):
    print(f"顔 {i+1}:")
    print(f"  境界ボックス: {face.bbox}")
    print(f"  キーポイント: {face.kps}")
    print(f"  検出信頼度: {face.det_score:.3f}")

4.3 顔認識と属性推定

目的:検出された顔から特徴ベクトルを抽出し、属性を推定する
期待される結果:512次元特徴ベクトル、年齢、性別、ランドマーク情報が出力される


# InsightFace顔解析プログラム
#   画像から顔検出・年齢・性別・特徴量抽出を行う包括的顔解析
#   論文: "ArcFace: Additive Angular Margin Loss for Deep Face Recognition" (CVPR 2019)
#   GitHub: https://github.com/deepinsight/insightface
#   特徴: ArcFaceアルゴリズムによる高精度顔認識、512次元特徴ベクトル抽出
#         年齢・性別推定、顔ランドマーク検出機能を統合
#   学習済モデル: Buffalo_lモデル(高精度な顔検出・認識用事前学習モデル)
#   前準備: pip install insightface onnxruntime

from insightface.app import FaceAnalysis
from insightface.data import get_image as ins_get_image

# 顔解析アプリケーションを初期化
app = FaceAnalysis()
app.prepare(ctx_id=0, det_size=(640, 640))

# サンプル画像を読み込み
img = ins_get_image('t1')

# メイン処理
faces = app.get(img)

# 結果出力
for i, face in enumerate(faces):
    print(f"顔 {i+1}:")
    print(f"  特徴ベクトル次元: {len(face.embedding)}")
    print(f"  年齢: {face.age:.1f}歳")
    print(f"  性別: {'男性' if face.gender == 1 else '女性'}")

    if hasattr(face, 'kps') and face.kps is not None:
        print(f"  顔ランドマーク: 利用可能")
    if hasattr(face, 'landmark_2d_106') and face.landmark_2d_106 is not None:
        print(f"  2D 106点ランドマーク: 利用可能")
    if hasattr(face, 'landmark_3d_68') and face.landmark_3d_68 is not None:
        print(f"  3D 68点ランドマーク: 利用可能")

print(f"\n実行結果の解釈:")
print(f"- 特徴ベクトル: 顔の特徴を512次元の数値で表現")
print(f"- 年齢・性別: 深層学習モデルによる推定値")
print(f"- ランドマーク: 顔の特徴点座標(目、鼻、口など)")

第5章 応用実装とシステム構築

5.1 顔検出のみの実行

目的:認識機能を使わず、検出とランドマーク検出のみを実行する
期待される結果:顔位置とキーポイントのみが出力される


# InsightFace顔検出プログラム
#   静的画像からの顔検出と特徴点抽出
#   論文: "RetinaFace: Single-Shot Multi-Level Face Localisation in the Wild" (CVPR 2020)
#   GitHub: https://github.com/deepinsight/insightface
#   特徴: InsightFaceは高精度な顔検出・認識ライブラリ、RetinaFaceベースの検出器搭載
#         WIDER FACEデータセットで最高精度、リアルタイム処理対応
#   学習済モデル: buffalo_l(高精度汎用モデル)- 多様な顔向き・照明条件に対応
#   前準備: pip install insightface opencv-python onnxruntime

from insightface.app import FaceAnalysis
import cv2

# 顔検出器の初期化
app = FaceAnalysis(allowed_modules=['detection'])
app.prepare(ctx_id=0, det_size=(640, 640))

# 画像読み込み
img = cv2.imread('test.jpg')

# 顔検出実行
faces = app.get(img)

# 結果出力
for i, face in enumerate(faces):
    bbox = face.bbox
    kps = face.kps
    print(f"顔 {i+1}:")
    print(f"  顔の位置: {bbox}")
    print(f"  キーポイント: {kps}")

5.2 顔照合システム

目的:2つの顔画像が同一人物かを判定する
期待される結果:類似度スコアと同一人物判定結果が出力される


# InsightFace顔認識照合プログラム
#   2つの画像から顔の特徴ベクトルを抽出してコサイン類似度による同一人物判定
#   論文: "ArcFace: Additive Angular Margin Loss for Deep Face Recognition" (CVPR 2019)
#   GitHub: https://github.com/deepinsight/insightface
#   特徴: ArcFaceは角度マージンを用いた損失関数により高精度な顔認識を実現
#         LFWデータセットで99.83%の精度、Windows環境対応
#   学習済モデル: Buffalo_l(512次元特徴ベクトル、高精度汎用モデル)
#   前準備: pip install insightface opencv-python numpy

from insightface.app import FaceAnalysis
import numpy as np
import cv2

# 定数定義
THRESHOLD = 0.6
IMAGE1_PATH = 'person1.jpg'
IMAGE2_PATH = 'person2.jpg'

# 顔検出と認識の初期化
app = FaceAnalysis(allowed_modules=['detection', 'recognition'])
app.prepare(ctx_id=0, det_size=(640, 640))

# 画像読み込み
img1 = cv2.imread(IMAGE1_PATH)
img2 = cv2.imread(IMAGE2_PATH)

# 顔検出実行
faces1 = app.get(img1)
faces2 = app.get(img2)

# 特徴ベクトル抽出
face1_embedding = faces1[0].embedding
face2_embedding = faces2[0].embedding

# メイン処理
# コサイン類似度計算
similarity = np.dot(face1_embedding, face2_embedding) / (
    np.linalg.norm(face1_embedding) * np.linalg.norm(face2_embedding)
)

# 同一人物判定
is_same = similarity > THRESHOLD

# 結果出力
print(f"類似度: {similarity:.3f}")
print(f"同一人物: {'はい' if is_same else 'いいえ'}")
print(f"判定基準: 類似度が{THRESHOLD}以上で同一人物と判定")

第6章 性能最適化と実践的応用

6.1 性能最適化のベストプラクティス

6.1.1 モデル選択による最適化

軽量化が必要な場合:

精度を重視する場合:

6.1.2 処理速度の最適化

# GPU使用時の最適化設定
app = FaceAnalysis(
    name='buffalo_l',
    providers=['CUDAExecutionProvider'],  # GPUのみ指定
)
app.prepare(ctx_id=0, det_size=(640, 640))

# バッチ処理による高速化
def process_multiple_images(images):
    results = []
    for img in images:
        faces = app.get(img)
        results.append(faces)
    return results

大量の画像を処理する際は、メモリリークを防ぐため定期的にガベージコレクションを実行することが推奨される。また、不要な中間結果は速やかに削除することが推奨される。

6.1.3 精度向上のテクニック


# 高解像度入力による精度向上
app.prepare(ctx_id=0, det_size=(1024, 1024))

# 顔領域の前処理
def preprocess_face_region(img, bbox):
    """顔領域を切り出して正規化"""
    x1, y1, x2, y2 = bbox.astype(int)
    face_img = img[y1:y2, x1:x2]

    # ヒストグラム平坦化による照明正規化
    face_gray = cv2.cvtColor(face_img, cv2.COLOR_BGR2GRAY)
    face_eq = cv2.equalizeHist(face_gray)
    face_normalized = cv2.cvtColor(face_eq, cv2.COLOR_GRAY2BGR)

    return face_normalized

6.2 基本的な顔照合

目的:2つの顔画像の類似度を計算する
期待される結果:コサイン類似度と同一人物判定結果が出力される


# InsightFace顔認識類似度計算プログラム
#   2枚の画像から顔の特徴を抽出し類似度を計算して同一人物判定を行う
#   論文: "ArcFace: Additive Angular Margin Loss for Deep Face Recognition" (CVPR 2019)
#   GitHub: https://github.com/deepinsight/insightface
#   特徴: ArcFaceは角度マージンを用いた顔認識手法、高精度な顔認識を実現
#         コサイン類似度による類似度計算、閾値による同一人物判定機能
#   学習済モデル: InsightFaceの事前学習済みモデル(RetinaFace検出+ArcFace認識)
#   前準備: pip install insightface opencv-python numpy

from insightface.app import FaceAnalysis
import numpy as np
import cv2

# 定数定義
DETECTION_SIZE = (640, 640)
SIMILARITY_THRESHOLD = 0.6
IMAGE1_PATH = 'person1.jpg'
IMAGE2_PATH = 'person2.jpg'

# InsightFace初期化
app = FaceAnalysis(allowed_modules=['detection', 'recognition'])
app.prepare(ctx_id=0, det_size=DETECTION_SIZE)

# 類似度計算関数
def calculate_similarity(embedding1, embedding2):
    return np.dot(embedding1, embedding2) / (
        np.linalg.norm(embedding1) * np.linalg.norm(embedding2)
    )

# メイン処理
# 画像読み込み
img1 = cv2.imread(IMAGE1_PATH)
img2 = cv2.imread(IMAGE2_PATH)

# 顔検出・特徴抽出
faces1 = app.get(img1)
faces2 = app.get(img2)

# 類似度計算
face1_embedding = faces1[0].embedding
face2_embedding = faces2[0].embedding
similarity = calculate_similarity(face1_embedding, face2_embedding)
is_same_person = similarity > SIMILARITY_THRESHOLD

# 結果出力
print(f"類似度: {similarity:.3f}")
print(f"同一人物判定: {'はい' if is_same_person else 'いいえ'}")
print(f"判定基準: 類似度が{SIMILARITY_THRESHOLD}以上で同一人物と判定")

6.3 写真整理アプリケーション

目的:複数の写真を顔の類似度でグループ化する
期待される結果:同一人物の写真がグループにまとめられる


# InsightFace顔認識クラスタリングプログラム
#   複数画像から顔特徴量を抽出し類似度でグループ化
#   論文: "ArcFace: Additive Angular Margin Loss for Deep Face Recognition" (CVPR 2019)
#   GitHub: https://github.com/deepinsight/insightface
#   特徴: InsightFaceは深層学習ベースの顔認識ライブラリ、高精度な顔検出・認識機能
#         ArcFaceアルゴリズムによる512次元特徴量抽出、コサイン類似度による類似判定
#   学習済モデル: Buffalo_l(精度重視の大型モデル)、RetinaFace検出器とArcFace認識器
#   前準備: pip install insightface opencv-python numpy

from insightface.app import FaceAnalysis
import numpy as np
import cv2
from pathlib import Path

# 定数定義
SIMILARITY_THRESHOLD = 0.6
DETECTION_SIZE = (640, 640)
IMAGE_PATHS = ['photo1.jpg', 'photo2.jpg', 'photo3.jpg', 'photo4.jpg']

# 顔認識アプリケーション初期化
app = FaceAnalysis(allowed_modules=['detection', 'recognition'])
app.prepare(ctx_id=0, det_size=DETECTION_SIZE)

# 各写真から顔特徴を抽出
face_data = []
for img_path in IMAGE_PATHS:
    if not Path(img_path).exists():
        continue

    img = cv2.imread(img_path)
    if img is None:
        continue

    faces = app.get(img)
    if len(faces) > 0:
        face_data.append({
            'path': img_path,
            'embedding': faces[0].embedding
        })

# 顔グループの作成
groups = []
for face in face_data:
    placed = False
    for group in groups:
        # コサイン類似度計算
        similarity = np.dot(face['embedding'], group[0]['embedding']) / (
            np.linalg.norm(face['embedding']) * np.linalg.norm(group[0]['embedding'])
        )
        if similarity > SIMILARITY_THRESHOLD:
            group.append(face)
            placed = True
            break
    if not placed:
        groups.append([face])

# 結果出力
if len(groups) == 0:
    print("処理可能な顔データがありません")
else:
    print("=== 顔認識クラスタリング結果 ===")
    for i, group in enumerate(groups):
        print(f"グループ {i+1} ({len(group)}枚):")
        for face in group:
            print(f"  {face['path']}")

    print(f"\n総グループ数: {len(groups)}個")
    print(f"類似度閾値: {SIMILARITY_THRESHOLD}")

6.4 出欠確認アプリケーション

目的:教室写真から登録済み学生の出席を確認する
期待される結果:出席者リストと欠席者リストが出力される


# InsightFace顔認識出席確認システム
#   教室写真から学生の出席状況を自動判定
#   論文: "ArcFace: Additive Angular Margin Loss for Deep Face Recognition" (CVPR 2019)
#   GitHub: https://github.com/deepinsight/insightface
#   特徴: ArcFaceは角度マージンを導入した高精度顔認識手法、単位球面上での特徴表現
#         顔認識精度LFW 99.83%、MegaFace 98.35%、Windows環境対応
#   学習済モデル: Buffalo_l(精度重視)、Buffalo_s(速度重視)から選択可能
#   前準備: pip install insightface opencv-python numpy

from insightface.app import FaceAnalysis
import numpy as np
import cv2
from pathlib import Path

# 定数定義
DETECTION_SIZE = (640, 640)
SIMILARITY_THRESHOLD = 0.6
CLASSROOM_IMAGE = 'classroom.jpg'

# InsightFace初期化
app = FaceAnalysis(allowed_modules=['detection', 'recognition'])
app.prepare(ctx_id=0, det_size=DETECTION_SIZE)

# 事前登録学生データ
registered_students = {
    'student001': np.array([...]),
    'student002': np.array([...]),
    'student003': np.array([...])}

# 教室写真の読み込み
img_path = Path(CLASSROOM_IMAGE)
img = cv2.imread(str(img_path))

# メイン処理
faces = app.get(img)
present_students = []

for face in faces:
    face_embedding = face.embedding
    for student_id, registered_embedding in registered_students.items():
        similarity = np.dot(face_embedding, registered_embedding) / (
            np.linalg.norm(face_embedding) * np.linalg.norm(registered_embedding)
        )
        if similarity > SIMILARITY_THRESHOLD:
            if student_id not in present_students:
                present_students.append(student_id)
            break

all_students = list(registered_students.keys())
absent_students = [s for s in all_students if s not in present_students]

# 結果出力
print(f"出席者: {present_students}")
print(f"欠席者: {absent_students}")
print(f"出席率: {len(present_students)}/{len(all_students)}")

第7章 用語集