人脸属性检测算法

Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.


本章介绍人脸属性检测 SDK 的算法能力、接口调用、部署准备、工程构建和运行排查。SDK 通过 ModelInfer/RKNN 在 RK3576 NPU 上执行图像推理。

SDK 采用 WiderFace 人脸检测与 FER 属性分类级联流程,输出人脸框、表情、年龄估计和性别分类结果。

../../../_images/image_BZeRbk5zfo7GkNxy956cxowvn1g.webp

算法能力

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 个年龄段

表情、年龄和性别均为模型估计。年龄结果是预测值,表情和性别分数表示模型输出,不代表经独立核验的个人信息。

部署前准备

资源获取

资源包

说明

facial_attributes_detection_RK3576

算法SDK,包含公开头文件、算法库、ModelInfer/RKNN/OpenCV 运行库、检测与 FER 模型、样例图

facial_attributes_project示例工程

包含 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 只表示本次调用成功;合法成功结果也可能是零张人脸。

返回结果

字段

内容

输出说明

box

shared_ptr``:x/y/width/height/score/class_id

绘制人脸框、显示检测分数、写入 JSON

emotion

scores[8] 和 emotion_type

七类表情标签及模型分数

age_gender.age

SDK 计算的整数年龄估计

根据九类年龄段分数加权计算

age_gender.gender_scores[2]

[female, male] 分数

与 gender_type 类别结果对应

表情分数索引依次对应 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 解析失败;兼容接口保留

公开类还提供以下方法:

方法

用途

save_result(img_src, results, output_path, image_path, save_img, save_labelme_json)

按选项保存检测标注图和 LabelMe JSON

get_benchmark_info(img_src, repeat_times)

对输入图像重复推理并输出耗时统计;repeat_times 默认值为 100

uinit()

反初始化并释放 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 集成到程序时,可按以下顺序组织生命周期:

  1. 由应用负责取得输入图像。静态图可使用 cv::imread();摄像头场景由应用的视频采集模块取得帧。

  2. 将图像转换为 SDK 要求的三通道 BGR 连续内存;非连续图像需先 clone()。

  3. 创建 FacialAttributesDetection 实例并调用 set_param() 设置检测阈值。

  4. 调用 init() 加载检测/FER 模型并传入设备授权文件路径、module 3 和算法授权码。

  5. 检查 init() 返回值及 get_status(0);初始化成功后调用 inference()。

  6. 遍历 FaceContext 结果,读取检测框、表情分数、年龄估计及性别分类结果。

  7. 按应用需求使用 save_result() 导出 SDK 标注图/LabelMe JSON,或自行序列化结果;需要测量推理性能时调用 get_benchmark_info()。

  8. 处理结束后调用 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 根据网络探测和授权结果执行拒绝或其定义的离线试用策略。

常见问题

现象

检查方向

init() 返回 FACIAL_INIT_ERROR,授权状态为 100014

检查 FAD_AUTH_CODE 是否仍为占位符或为空,并确认网络和授权配置。license 文件不是授权码

inference() 成功但结果向量为空

当前图像可能没有达到阈值的人脸;确认输入非空、为 BGR 三通道,并检查人脸尺寸、清晰度和检测阈值

出现多个重叠框

适当降低 NMS IoU 以加强重复框抑制;同时检查检测阈值

摄像头采集失败

用 v4l2-ctl --list-devices 查看采集设备;确认使用 USB V4L2 节点,并检查运行用户是否有 video 设备访问权限

Could not load ... .so

检查 setup_from_sdk.sh 是否使用了 RK3576 Linux SDK,确认 lib/ 文件齐全并通过 run.sh 启动

-Wclass-memaccess 警告

警告来自 SDK 公开头文件的 memset(Point[]);不要改 SDK 文件,确认构建本身是否成功

保存失败

检查工程 outputs/ 是否可写、磁盘空间是否足够;不要在 root 和 pi 用户之间混用生成目录