人脸属性检测算法¶
Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.
本章介绍人脸属性检测 SDK 的算法能力、接口调用、部署准备、工程构建和运行排查。SDK 通过 ModelInfer/RKNN 在 RK3576 NPU 上执行图像推理。
SDK 采用 WiderFace 人脸检测与 FER 属性分类级联流程,输出人脸框、表情、年龄估计和性别分类结果。
算法能力¶
SDK 在一张 BGR 图像上执行级联推理:
BGR 图像 → WiderFace 检测 → 人脸裁剪 → FER 属性分类 → 输出检测框及表情、年龄、性别结果
能力 |
输出 |
说明 |
|---|---|---|
人脸检测 |
人脸框 x/y/width/height、检测分数 |
坐标对应输入原图像素 |
表情分类 |
Neutral、Happy、Sad、Surprise、Fear、Disgust、Anger 七类及分数 |
输出模型分类结果及各类别分数 |
年龄估计 |
一个整数年龄 |
根据九个年龄段的分类分数和代表年龄加权计算并取整 |
性别分类 |
Female、Male 标签及两个分数 |
模型二分类估计,不代表已核实的个人信息 |
多人脸 |
每张检测到的人脸各有一份属性结果 |
每个人脸分别返回检测框和属性分类结果 |
模型文件位于部署后的 models/:
文件 |
用途 |
|---|---|
RK3576_Ubuntu_widerface_last.engine |
WiderFace 人脸检测 |
RK3576_Ubuntu_FER_best.engine |
FER 分类:7 类表情、2 类性别、9 个年龄段 |
表情、年龄和性别均为模型估计。年龄结果是预测值,表情和性别分数表示模型输出,不代表经独立核验的个人信息。
部署前准备¶
资源获取¶
资源包 |
说明 |
|---|---|
|
算法SDK,包含公开头文件、算法库、ModelInfer/RKNN/OpenCV 运行库、检测与 FER 模型、样例图 |
包含 SDK 调用示例、构建文件及依赖准备和运行脚本 |
SDK 应与 RK3576 Debian aarch64 平台匹配;应用通过 SDK 公开接口调用算法。
RK3576 Linux SDK 的关键目录如下:
facial_attributes_detection_RK3576/
├── include/
│ └── facial_attributes_detection.h
├── lib/
│ └── libfacial_attributes_detection.so
├── 3rd_party/
│ ├── modelinfer/
│ ├── rknn/
│ └── opencv/
├── models/
│ ├── RK3576_Ubuntu_widerface_last.engine
│ └── RK3576_Ubuntu_FER_best.engine
├── images/
│ └── input.jpg
└── example.cpp
具体以 SDK 随附的 README_SDK.md 为准。请使用 RK3576 Linux 版本,不要混用 RK3568、Android 或其他版本的动态库和模型。
硬件与系统要求¶
项目 |
要求 |
|---|---|
主控 |
Quectel Pi M2 |
系统 |
Debian aarch64 |
USB摄像头 |
可选 USB V4L2 摄像头;使用摄像头输入时需要 |
设备访问 |
PC 可通过 ADB 连接开发板;运行用户需要具备工程文件及摄像头设备访问权限 |
软件依赖¶
算法运行依赖 SDK 附带的 ModelInfer、RKNN 和 OpenCV world 库。编译本仓库示例工程需要 C++17 编译器、Make、pkg-config 和 Qt5 Widgets 开发包。联网安装编译依赖时可执行:
sudo apt update
sudo apt install -y build-essential pkg-config qtbase5-dev
检查工具链:
g++ --version
make --version
pkg-config --exists Qt5Widgets && echo "Qt5 OK"
v4l2-ctl --version
v4l2-ctl 用于枚举和排查摄像头设备。SDK 与 OpenCV 运行库应使用同一 RK3576 Linux SDK 交付版本。
项目结构¶
facial_attributes_project/
├── src/
│ └── facial_attributes_cam_demo.cpp SDK 接口调用和图像输入处理
├── Makefile C++17 编译和链接规则
├── build.sh 并行调用 make
├── setup_from_sdk.sh 从 SDK 复制头文件、动态库和模型
├── run.sh 配置运行库路径及授权码
├── include/ SDK 公开头和 OpenCV 头文件(准备依赖后生成)
├── lib/ SDK 及 ModelInfer/RKNN/OpenCV 动态库(准备依赖后生成)
├── models/ 检测和 FER 模型(准备依赖后生成)
├── images/ SDK 示例图 input.jpg(准备依赖后生成)
├── license/ SDK 生成的设备绑定授权文件
├── outputs/ 示例程序导出的结果文件
└── facial_attributes_cam_demo 编译生成的示例可执行文件
include/、lib/、models/ 和 images/ 由 setup_from_sdk.sh 从匹配的 RK3576 Linux SDK 交付包生成。部署前请取得对应 SDK 及所需授权许可。
算法 SDK 接口¶
SDK 公开头文件为 include/facial_attributes_detection.h,级联入口类为 FacialAttributesDetection。RK3576 的 module 参数为 3;算法 appid 147 由 SDK 内部管理。
初始化与生命周期¶
以下代码展示 SDK 初始化的基本流程,应放在函数体内调用:
FacialAttributesDetection sdk;
float confidence = 0.25f;
float nmsIou = 0.20f;
float detectionFilter = 0.0f;
float classificationFilter = 0.0f;
sdk.set_param(confidence, nmsIou, detectionFilter, classificationFilter);
std::string detector = "models/RK3576_Ubuntu_widerface_last.engine";
std::string classifier = "models/RK3576_Ubuntu_FER_best.engine";
std::string license = "license/fad_license.txt";
std::string authCode = std::getenv("FAD_AUTH_CODE") ? std::getenv("FAD_AUTH_CODE") : "";
const auto result = sdk.init(detector.data(), classifier.data(), license.data(), 3, authCode.data());
if (result != FACIAL_PROCESS_OK || sdk.get_status(0) != 0) {
return;
}
std::string::data() 在 C++17 中返回可写字符存储,符合 SDK 的 char* 参数签名。模型路径相对于应用的工作目录。应用结束时调用 sdk.uinit() 释放资源。
get_status(0) 是算法初始化状态;get_status(1) 是授权状态。调用方应在初始化成功后再调用推理接口。
set_param 的完整签名还有 scoreThresh_det 和 scoreThresh_cla 两项:前者是检测结果输出过滤阈值,后者为跨平台接口保留参数,RK3576 SDK 当前未使用。示例将两者设置为 0.0。
输入约定与推理¶
SDK inference 的输入是 BGR 连续内存、行数、列数和通道数:
std::vector<facial_info::FaceContext> faces;
if (!bgr.isContinuous()) bgr = bgr.clone();
const auto result = sdk.inference(bgr.data, bgr.rows, bgr.cols, bgr.channels(), faces);
cv::imread(..., cv::IMREAD_COLOR)和 V4L2/OpenCV 采集帧均按 BGR 处理;通道数应为 3。非连续 ROI 在送入 SDK 前复制为连续矩阵。
SDK 内部负责 FER 所需的颜色转换和模型预处理,调用方不应重复归一化或转换为 RGB 后直接传入。
faces是输出参数;调用成功后包含每张检测人脸的facial_info::FaceContext。应用应检查检测框坐标和尺寸后再使用结果。FACIAL_PROCESS_OK只表示本次调用成功;合法成功结果也可能是零张人脸。
返回结果¶
字段 |
内容 |
输出说明 |
|---|---|---|
|
|
绘制人脸框、显示检测分数、写入 JSON |
|
|
七类表情标签及模型分数 |
|
SDK 计算的整数年龄估计 |
根据九类年龄段分数加权计算 |
|
|
与 |
表情分数索引依次对应 0 Neutral、1 Happy、2 Sad、3 Surprise、4 Fear、5 Disgust、6 Anger。
年龄模型输出九类分布,SDK 按代表年龄 1/6/14/24/34/44/54/64/75 加权并取整。年龄、表情和性别结果均为模型估计。
SDK 返回码与授权状态¶
常见 FACIAL_ATTRIBUTES_DETECTION_RES_CODE:
返回码 |
名称 |
说明 |
|---|---|---|
0 |
FACIAL_PROCESS_OK |
当前操作成功 |
-1 |
FACIAL_INIT_ERROR |
初始化失败,包括模型或授权失败 |
-2 |
FACIAL_UNINIT_ERROR |
尚未初始化 |
-3 |
FACIAL_ERR_INFERENCE_ERROR |
推理失败 |
-4 |
FACIAL_ERR_IMAGE_EMPTY |
图像为空或尺寸/通道不合法 |
-5 |
FACIAL_ERR_JSON_NULL |
JSON 结果为空;兼容接口保留 |
-6 |
FACIAL_ERR_JSON_PARSE |
JSON 解析失败;兼容接口保留 |
公开类还提供以下方法:
方法 |
用途 |
|---|---|
|
按选项保存检测标注图和 LabelMe JSON |
|
对输入图像重复推理并输出耗时统计; |
|
反初始化并释放 SDK 内部推理资源 |
算法授权分两层,由 SDK 实现并严格执行“引擎授权 → 算法授权 → 引擎初始化”的顺序。L1 引擎层使用引擎内部 appid 133 身份,由 SDK 在初始化流程中处理。应用传入 module 3 和算法授权码,供 L2 算法 appid 147 校验。授权流程和状态映射以 SDK 文档为准。
get_status(1) |
常见含义 |
|---|---|
0 |
正式授权成功 |
100014 |
常见于未提供授权码或无有效本地授权件;在 LicenseSDK V2.2.9 的离线流程中也可能作为离线返回码,需结合 init()、初始化状态和 SDK 版本判断 |
100010 |
授权相关状态;是否进入试用由 SDK 的网络探测及授权流程决定 |
100002 |
算法试用到期 |
其他非零值 |
SDK/LicenseSDK 返回的授权错误码 |
具体授权策略、服务器判定和状态映射以随包 SDK 的 README_SDK.md 为准。首次正式授权可能需要联网
SDK 集成流程¶
将 SDK 集成到程序时,可按以下顺序组织生命周期:
由应用负责取得输入图像。静态图可使用
cv::imread();摄像头场景由应用的视频采集模块取得帧。将图像转换为 SDK 要求的三通道 BGR 连续内存;非连续图像需先
clone()。创建
FacialAttributesDetection实例并调用set_param()设置检测阈值。调用
init()加载检测/FER 模型并传入设备授权文件路径、module3和算法授权码。检查
init()返回值及get_status(0);初始化成功后调用inference()。遍历
FaceContext结果,读取检测框、表情分数、年龄估计及性别分类结果。按应用需求使用
save_result()导出 SDK 标注图/LabelMe JSON,或自行序列化结果;需要测量推理性能时调用get_benchmark_info()。处理结束后调用
uinit()释放 SDK 资源。
连续视频处理时,应由应用控制采集和推理调度,避免对同一 SDK 实例进行并发推理调用。若需要保持数据采集不阻塞业务主线程,可将采集和推理放入工作线程,并通过线程安全的数据结构传递帧与结果。
部署与运行¶
SDK 目录要求¶
setup_from_sdk.sh 的参数应指向 RK3576 Linux SDK 根目录,目录内容见“部署前准备”。该脚本会把 SDK 公开头文件、运行库、模型和样例图复制到工程对应目录。
传输工程与 SDK¶
在 Windows PowerShell 中将工程和 SDK 推送到设备临时目录:
adb devices
adb push "<SDK 主机路径>" /tmp/facial_attributes_detection_RK3576
adb push "facial_attributes_project" /tmp/
在 Quectel Pi M2 终端中将文件复制到 pi 用户家目录。
sudo mkdir -p "$HOME/facial_attributes_detection_RK3576" "$HOME/facial_attributes_project"
sudo cp -a /tmp/facial_attributes_detection_RK3576/. "$HOME/facial_attributes_detection_RK3576/"
sudo cp -a /tmp/facial_attributes_project/. "$HOME/facial_attributes_project/"
sudo chown -R "$USER:$(id -gn)" \
"$HOME/facial_attributes_detection_RK3576" \
"$HOME/facial_attributes_project"
编译¶
板端以普通桌面用户(示例为 pi)编译:
sudo apt update
sudo apt install -y build-essential pkg-config qtbase5-dev qtwayland5
cd /home/pi/facial_attributes_project
sh setup_from_sdk.sh /home/pi/facial_attributes_detection_RK3576
sh build.sh
不传 SDK 路径时,脚本默认使用 $HOME/facial_attributes_detection_RK3576。build.sh 按在线 CPU 数调用 make。Makefile 用 C++17 编译 src/facial_attributes_cam_demo.cpp,从工程 include/、lib/ 查找 SDK 头文件和库,链接 libfacial_attributes_detection.so、libopencv_world.so、Qt5 开发库及系统线程/动态加载库,生成 facial_attributes_cam_demo。
SDK 公开头的 Landmarks 构造函数对带自定义构造函数的 Point 数组调用 memset,某些 GCC 版本可能输出 -Wclass-memaccess 警告。这是 SDK 头文件产生的警告;本项目不修改供应商 SDK。不要为了消除它而提交修改过的 SDK 头或二进制。
运行示例程序¶
cd /home/pi/facial_attributes_project
sh run.sh
run.sh 设置 LD_LIBRARY_PATH、默认 license 路径和 FAD_AUTH_CODE,然后启动 SDK 集成示例。建议以拥有工程文件和摄像头设备访问权限的普通用户运行。
授权配置¶
算法 module 对 RK3576 固定为 3。项目中的 run.sh 含占位符:
export FAD_AUTH_CODE="${FAD_AUTH_CODE:-REPLACE_WITH_ALGORITHM_AUTH_CODE}"
将占位符替换为 授权码;也可通过环境变量 FAD_AUTH_CODE 覆盖。授权码缺失或校验失败时,SDK 根据网络探测和授权结果执行拒绝或其定义的离线试用策略。
常见问题¶
现象 |
检查方向 |
|---|---|
|
检查 |
|
当前图像可能没有达到阈值的人脸;确认输入非空、为 BGR 三通道,并检查人脸尺寸、清晰度和检测阈值 |
出现多个重叠框 |
适当降低 NMS IoU 以加强重复框抑制;同时检查检测阈值 |
摄像头采集失败 |
用 |
|
检查 |
|
警告来自 SDK 公开头文件的 |
保存失败 |
检查工程 |