顔98キーポイント認識
修正履歴
| NO | バージョン | 修正内容 | 修正日 |
|---|---|---|---|
| 1 | Ver1.0 | 新規作成 | 2026/06/30 |
この文書の情報は、文書を改善するため、事前の通知なく変更されることがあります。最新版は弊社ホームページからご参照ください。
株式会社日昇テクノロジーの書面による許可のない複製は、いかなる形態においても厳重に禁じられています。
1. 顔キーポイント概要
顔キーポイント位置特定は、顔キーポイント検出または顔アライメントとも呼ばれます。入力された顔画像に対して、眉、目、鼻、口、顔の輪郭など、顔面上の重要領域の位置を推定する処理です。顔検出と同様に、姿勢変化や遮蔽などの影響を受けるため、顔キーポイント検出も難易度の高いタスクです。
顔キーポイント検出には、さまざまな重要な応用シーンがあります。
・顔姿勢アライメント:顔認識などのアルゴリズムでは、モデル精度を向上させるために顔姿勢のアライメントが必要です。
・顔補正・顔編集:キーポイントに基づいて顔型、目の形状、鼻の形状などを正確に解析し、顔の特定部位を加工することで、顔エフェクト、美顔処理、スタンプ貼り付けなどのエンターテインメント機能を実現できます。
・表情解析・唇認識:キーポイントに基づいて顔表情を解析し、インタラクティブエンターテインメントや行動予測などのシーンに使用できます。
本顔98点キーポイントアルゴリズムの、キーポイント位置は次の図に示します:

図1-1 顔98キーポイントのインデックス定義
データセットでのアルゴリズム性能:
| 顔ランドマークアルゴリズム | NME(%) |
| 300W | 2.78 |
| COFW | 3.08 |
| AFLW | 1.42 |
CSUN RV1126Bでの実行効率:
| アルゴリズム種別 | モデルサイズ | 実行効率 |
| face_detect | 44.23MB | 17ms |
| face_landmark98 | 10.88MB | 23ms |
2. クイックスタート
2.1 開発環境の準備
本ドキュメントを初めてお読みになる場合は、『入門ガイド/開発コンパイル環境の準備と更新』を参照し、関連する手順に従ってコンパイル環境をデプロイしてください。
PC側のUbuntuシステムで run スクリプトを実行し、Docker開発環境に入ります。手順は次のとおりです。
cd ~/linuxshare/work/rv1126b/jp/embedded/images/develop_environment./run.sh 2204
図2-1 Docker開発環境の起動
2.2 ソースコードのダウンロード
Docker開発環境で、ソースコードリポジトリを保存する管理ディレクトリを作成します。
cd /opt/linuxshare/work/rv1126b/jp/AI/demo/ai-algorithmgitツールを使用して、管理ディレクトリ内にリモートリポジトリをクローンします。
git clone https://github.com/csunltd/rv1126b-ai-toolkit.git※GitHubのWebページからダウンロードする場合でも、リポジトリ全体をダウンロードしてください。本サンプルに対応するディレクトリだけを単独でダウンロードしないでください。
※すでにダウンロードした場合、飛ばしてください。
2.3 モデルデプロイ
アルゴリズムDemoを実行するには、まず人体キーポイント認識アルゴリズムモデルをダウンロードする必要があります。
ダウンロードリンク:
顔検出モデル:
https://dl.dragonwake.com/download/rv1126b/AI/demo/01_face-detect.zip
顔キーポイント認識モデル:
https://dl.dragonwake.com/download/rv1126b/AI/demo/11_face_landmark98.zip
その後、ダウンロードした顔検出モデルと人体キーポイント認識モデルを Release/ ディレクトリへコピーしてください。

図2-2 Releaseディレクトリ内のファイル配置
2.4 サンプルのビルド
サンプルがあるディレクトリに移動してビルドを実行します。具体的なコマンドは次のとおりです。
cd rv1126b-ai-toolkit/Demos/algorithm-face_landmark98/./build.sh cpres* 依存ライブラリは開発ボード上に配置されているため、クロスコンパイル中は /mnt のマウントを保持する必要があります。
sudo mount -t nfs -o vers=3,proto=tcp,mountproto=tcp,nolock,retrans=5,timeo=5 192.168.10.85:/ /mnt* build.sh スクリプトに cpres パラメータを指定すると、Release/ ディレクトリ内のすべてのリソースが開発ボードへコピーされます。

図2-3 サンプルビルド結果
2.5 サンプル実行および結果
コンパイル済みのものを基板にコピーします。
cp Release/\* /mnt/userdata/Demo/algorithm-face_landmark98/※./build.sh cpresでコンパイルした場合、自動的にコピーされます。
シリアルデバッグまたはSSHデバッグで開発ボードのバックエンドに入り、次のようにサンプルのデプロイ先へ移動します。
cd /userdata/Demo/algorithm-face_landmark98/サンプルを実行するコマンドは次のとおりです。
./test-face-landmark98 test.jpg
図2-4 サンプル実行結果
Docker開発環境でテスト結果写真を基板からコピーしましょう。
cp /mnt/userdata/Demo/algorithm-face_landmark98/result.jpg .
図2-5 結果画像のコピーコマンド
認識結果は下図通りです。

図2-6 顔98キーポイント認識結果画像
APIの詳細説明およびAPI呼び出し(本サンプルのソースコード)については、以下を参照してください。
3. 顔検出API説明
3.1 参照方法
お客様がローカルプロジェクトでEASY EAI APIライブラリを直接呼び出せるようにするため、このリストにはプロジェクトにリンクする必要のあるライブラリとヘッダーファイルが表示されており、ユーザーがそれらを直接追加しやすくなっています。
| 項目 | 説明 |
| ヘッダファイルディレクトリ | easyeai-api/algorithm/face_detect |
| ライブラリファイルディレクトリ | easyeai-api/algorithm/face_detect |
| ライブラリリンクパラメータ | -lface_detect |
3.2 顔検出を初期化関数
顔検出を初期化関数プロトタイプは次のとおりです。
int face_detect_init(rknn_context \*ctx, const char \*path)詳細は次のとおりです。
| 関数名: face_detect_init() | |
| ヘッダファイル | face_detect.h |
| 入力パラメータ | ctx:rknn_contextハンドル |
| 入力パラメータ | path:アルゴリズムモデルのパス |
| 戻り値 | 成功時の戻り値:0 |
| 失敗時の戻り値:-1 | |
| 注意事項 | なし |
3.3 顔検出実行関数
顔検出実行関数face_detect_run原型次のとおりです。
int face_detect_run(rknn_context ctx, cv::Mat &input_image, std::vector\<det\> &result)詳細は次のとおりです。
| 関数名:face_detect_run() | |
| ヘッダファイル | face_detect.h |
| 入力パラメータ | ctx:rknn_contextハンドル |
| 入力パラメータ | input_image:画像データ入力(cv::MatはOpenCVの型) |
| 出力パラメータ | result:物体検出ボックス出力 |
| 戻り値 | 成功時の戻り値:0 |
| 失敗時の戻り値:-1 | |
| 注意事項 | なし |
3.4 顔検出解放関数
顔検出解放関数原型次のとおりです。
int face_detect_release(rknn_context ctx)詳細は次のとおりです。
関数名:face_detect_release ()
| ヘッダファイル | face_detect.h |
| 入力パラメータ | ctx:rknn_contextハンドル |
| 戻り値 | 成功時の戻り値:0 |
| 失敗時の戻り値:-1 | |
| 注意事項 | なし |
4. 顔98点ランドマークAPI説明
4.1 参照方法
お客様がローカルプロジェクトからEASY EAI APIライブラリを直接呼び出せるように、本プロジェクトでリンクする必必要がありますがあるライブラリおよびヘッダファイルなどを以下に示します。ユーザーはそのまま追加できます。
| 項目 | 説明 |
| ヘッダファイルディレクトリ | easyeai-api/algorithm_api/face_landmark98 |
| ライブラリファイルディレクトリ | easyeai-api/algorithm_api/face_landmark98 |
| ライブラリリンクパラメータ | -lface_landmark98 |
4.2 顔98点ランドマーク初期化関数
设置顔検出を初期化関数プロトタイプ次のとおりです。
int face_landmark98_init(rknn_face_landmark_context_t \*p_face_landmark, const char \*p_model_path)詳細は次のとおりです。
| 関数名: face_landmark98_init() | |
| ヘッダファイル | face_landmark98.h |
| 入力パラメータ | p_face_landmark:rknn_face_landmark_context_tハンドル |
| 入力パラメータ | p_model_path:アルゴリズムモデルのパス |
| 戻り値 | 成功時の戻り値:0 |
| 失敗時の戻り値:-1 | |
| 注意事項 | なし |
4.3 顔98点ランドマーク実行関数
设face_landmark98_run原型次のとおりです。
std::vector\<cv::Point\> face_landmark98_run(cv::Mat image, rknn_face_landmark_context_t \*p_face_landmark)詳細は次のとおりです。
| 関数名:face_landmark98_run () | |
| ヘッダファイル | face_landmark98.h |
| 入力パラメータ | p_face_landmark:rknn_face_landmark_context_tハンドル |
| 入力パラメータ | image:画像データ入力(cv::MatはOpenCVの型) |
| 戻り値 | std::vector<cv::Point>:アルゴリズム出力される顔ランドマーク座標 |
| 注意事項 | なし |
4.4 顔98点ランドマーク解放関数
顔98点ランドマーク解放関数原型次のとおりです。
int face_landmark98_release(rknn_face_landmark_context_t\* p_face_landmark)詳細は次のとおりです。
| 関数名:face_landmark98_release () | |
| ヘッダファイル | face_landmark98.h |
| 入力パラメータ | p_face_landmark:rknn_face_landmark_context_tハンドル |
| 戻り値 | 成功時の戻り値:0 |
| 失敗時の戻り値:-1 | |
| 注意事項 | なし |
5. 人体キーポイント認識サンプル
サンプルディレクトリとしてDemos/algorithm-face_landmark98/test-face-landmark98.cpp、操作フロー如以下。

図5-1 顔98キーポイント認識アルゴリズム処理フロー
参考サンプルは次のとおりです。
#include <stdio.h>#include <stdint.h>#include <stdlib.h>#include <fstream>#include <iostream>#include <vector>#include <fstream>#include <atomic>#include <queue>#include <thread>#include <mutex>#include <chrono>#include <sys/time.h>#include <sys/stat.h>#include <dirent.h>#include <unistd.h>
#include <opencv2/opencv.hpp>
#include <unistd.h>#include <sys/syscall.h>#include "face_detect.h"#include "face_landmark98.h"
using namespace std;using namespace cv;
int main(int argc, char **argv){
if( argc != 2) { printf("./test-face-landmark98 xxx.jpg \n"); return -1; }
struct timeval start; struct timeval end; float time_use=0;
rknn_context detect_ctx; std::vector<det> result; int ret;
cv::Mat src; src = cv::imread(argv[1], 1);
face_detect_init(&detect_ctx, "./face_detect.model");
/* 顔ランドマーク位置推定を初期化します */ rknn_face_landmark_context_t face_landmark;
ret = face_landmark98_init(&face_landmark, "./face_landmark98.model"); if( ret < 0) { printf("face_mask_judgement_init fail! ret=%d\n", ret); return -1; }
gettimeofday(&start,NULL); face_detect_run(detect_ctx, src, result);
gettimeofday(&end,NULL); time_use=(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);//マイクロ秒 printf("face_detect time_use is %f\n",time_use/1000);
printf("face num:%d\n", (int)result.size());
for (int i = 0; i < (int)result.size(); i++) { int x = (int)(result[i].box.x); int y = (int)(result[i].box.y); int w = (int)(result[i].box.width); int h = (int)(result[i].box.height); int max = (w > h)?w:h;
// 画像の切り出し範囲が境界を超えていないか確認します if( (x < 0) || (y < 0) || ((x +max) > src.cols) || ((y +max) > src.rows) ) { continue; }
// 顔位置 cv::Rect rect(x, y, w, h); cv::Mat face_roi =src(rect).clone();
gettimeofday(&start,NULL); std::vector<cv::Point> keys = face_landmark98_run(&face_landmark, face_roi);
gettimeofday(&end,NULL); time_use=(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);//マイクロ秒 printf("face_landmark time_use is %f\n",time_use/1000);
// 元画像上の位置 for (int i = 0; i < (int)keys.size(); i++) { keys[i].x += rect.x; keys[i].y += rect.y; }
for (int i = 0; i < (int)keys.size(); i++) { printf("keyPoints %d :[%d, %d]\n", i, keys[i].x, keys[i].y); cv::circle(src, keys[i], 2, CV_RGB(0, 255, 0), 2); }
//cv::rectangle(src, rect, CV_RGB(0, 255, 0), 2);
}
cv::imwrite("result.jpg", src);
/* 顔検出を解放します */ face_detect_release(detect_ctx);
/* 顔ランドマーク位置推定を解放します */ face_landmark98_release(&face_landmark);
return 0;}