Files
arcs/arcs-sdk/components/acomp/fd/README.rst
2026-08-13 16:50:52 +08:00

1036 lines
34 KiB
ReStructuredText
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
人脸识别组件
==============
简介
----
ACOMP FD (Face Detection) 是 ARCS SDK 的人脸识别组件,提供基于图像流的人脸检测、对齐、活体检测和特征提取功能。该组件支持多种图像格式输入,提供灵活的参数配置和事件回调机制。
主要特性
--------
- **完整人脸识别流程**:支持人脸检测、对齐、活体检测、特征提取和特征比对
- **多格式图像输入**:支持 YUYV422、RGB565、BGR888 等多种图像格式最大支持640*480分辨率
- **活体检测**:支持活体检测功能,可配置活体检测阈值
- **人脸特征管理**:支持人脸特征导入和比对,最多支持 10 个注册人脸
- **事件回调机制**:支持人脸识别结果、错误事件等多种事件通知
- **图像流管理**:提供完整的图像流通道管理和缓冲区操作接口
- **状态管理**:支持初始化、就绪、启动、停止等完整的生命周期管理
- **跨核通信**:基于 IPC 机制实现图像流的跨核传输
人脸识别基本流程
----------------
人脸识别基本流程如下图所示,实际根据业务需求,流程可能会有所不同:
.. image:: assets/face_detect_flow.png
:alt: 人脸识别基本流程
组件架构
--------
ACOMP FD 组件采用双核异构架构CP 核(应用核)通过 ACOMP IPC 框架与 AP 核(算法核)进行通信,实现人脸识别功能。
.. code-block:: text
┌─────────────────────────────────────────────────────────────────────┐
│ CP 核 (Application Core) │
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ 用户应用层 │ │
│ │ ┌────────────────────────────────────────────────────────┐ │ │
│ │ │ • 人脸识别事件回调处理 (检测结果/特征/活体) │ │ │
│ │ │ • 图像数据采集 (摄像头/图像文件) │ │ │
│ │ │ • 人脸特征管理 (注册/比对) │ │ │
│ │ └────────────────────┬───────────────────────────────────┘ │ │
│ └───────────────────────┼──────────────────────────────────────┘ │
│ │ │
│ ┌───────────────────────▼──────────────────────────────────────┐ │
│ │ ACOMP FD 组件 (CP 侧) │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ 生命周期管理 │ │ 事件回调管理 │ │ 参数配置接口 │ │ │
│ │ │ init/prepare │ │ add_callback │ │ params_set/ │ │ │
│ │ │ start/stop │ │ remove_cb │ │ live_detect │ │ │
│ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │
│ │ │ │ │ │ │
│ │ ┌──────▼─────────────────▼─────────────────▼───────┐ │ │
│ │ │ 图像流管理 (Stream API) │ │ │
│ │ │ • M2R 流: 图像输入 (camera → 算法) │ │ │
│ │ │ • tx_alloc/submit │ │ │
│ │ └──────────────────────┬───────────────────────────┘ │ │
│ └─────────────────────────┼──────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────▼─────────────────────────────────────┐ │
│ │ ACOMP IPC 层 (CP 侧) │ │
│ │ • IPC 消息封装 (NEW/FREE/CONTROL/NOTIFY) │ │
│ │ • 设备查询和管理 │ │
│ │ • 同步/异步命令处理 │ │
│ └─────────────────────────┬─────────────────────────────────────┘ │
└────────────────────────────┼────────────────────────────────────────┘
│ IC Message (IPC 消息通道)
┌────────────────────────────▼────────────────────────────────────────┐
│ AP 核 (Algorithm Core) │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ ACOMP Framework (AP 侧) │ │
│ │ │ │
│ │ • 接收 CP 核的 IPC 命令 (prepare/start/stop/control) │ │
│ │ • 处理图像流数据 (M2R 接收) │ │
│ │ • 执行人脸识别算法引擎 │ │
│ │ • 推送识别结果到 CP 核 (检测框/特征/活体) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 人脸识别算法引擎 (FD Engine) │ │
│ │ │ │
│ │ • 人脸检测 (Face Detection) │ │
│ │ • 人脸对齐 (Face Alignment) - 68个关键点 │ │
│ │ • 活体检测 (Liveness Detection) │ │
│ │ • 特征提取 (Feature Extraction) - 384维特征 │ │
│ │ • 特征比对 (Feature Comparison) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────┐
│ 共享内存 (Shared Mem) │
│ ┌────────────────────┐ │
│ │ VirtQueue 环形缓冲 │ │
│ │ (Stream IPC 数据) │ │
│ └────────────────────┘ │
└─────────────────────────┘
架构说明
~~~~~~~~
1. CP 核 (应用核) - 开放接口层
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- **用户应用层**: 处理人脸识别事件,采集图像数据,管理人脸特征
- **ACOMP FD 组件**: 提供生命周期管理、事件回调、参数配置等 API
- **图像流管理**: 管理 M2R(Master to Remote) 图像数据流
- **ACOMP IPC 层**: 封装 IPC 消息,与 AP 核通信
2. AP 核 (算法核) - 算法实现层
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- **ACOMP Framework**: 接收 IPC 命令,管理算法生命周期,处理图像流数据
- **人脸识别算法引擎**: 执行人脸检测、对齐、活体检测、特征提取和比对
.. note::
AP 核的具体实现为闭源算法库,开发者只需关注 CP 核的 API 使用即可。
3. 通信机制
^^^^^^^^^^^
- **控制通道**: 通过 IC Message 传递控制命令 (prepare/start/stop/control)
- **数据通道**: 通过 VirtQueue 共享内存实现零拷贝图像流传输
- **事件通知**: AP 核通过 NOTIFY 消息主动推送识别结果到 CP 核
4. 数据流向
^^^^^^^^^^^
- **M2R 流**: CP 核采集的图像数据 (摄像头/文件) → AP 核算法引擎
- **事件流**: AP 核识别结果(检测框/特征/活体) → CP 核回调函数
图像数据结构
------------
输入图像数据结构
~~~~~~~~~~~~~~~~
.. code-block:: c
typedef struct{
acomp_fd_pixel_format format; /* 像素格式 */
uint32_t index; /* 帧索引号 */
uint16_t width; /* 图像宽度(像素) */
uint16_t height; /* 图像高度(像素) */
uint32_t length; /* 图像数据长度(字节) */
uint32_t resv[4]; /* 保留字段 */
uint8_t data[0]; /* 图像数据 */
} acomp_fd_input_frame_t;
支持的图像格式
~~~~~~~~~~~~~~
.. list-table::
:header-rows: 1
:widths: 30 30 40
* - 格式
- 说明
- 数据大小 (320x240)
* - ``PIX_FMT_BGR888``
- BGR 24位真彩色
- 230400 字节
* - ``PIX_FMT_YUV422_YUYV_PACKED``
- YUYV422 交织格式
- 153600 字节
* - ``PIX_FMT_RGB565``
- RGB 16位高彩色
- 153600 字节
人脸识别结果结构
~~~~~~~~~~~~~~~~
.. code-block:: c
typedef struct {
acomp_fd_rect_t face_rect; /* 人脸检测矩形框 */
float face_score; /* 人脸检测得分 */
acomp_fd_align_point_t align_points[68]; /* 68个人脸关键点 */
int n_align_point; /* 关键点个数 */
acomp_fd_head_pose_t pose; /* 头部姿态角度 */
acomp_fd_live_detect_result_t live_result; /* 活体检测结果 */
int face_id; /* 人脸ID */
float features[384]; /* 384维人脸特征 */
int feature_cnt; /* 特征维度 */
float compare_scores[10]; /* 与注册人脸的比对得分 */
int compare_cnt; /* 已注册人脸数量 */
} acomp_fd_result_t;
配置选项
--------
基本配置
~~~~~~~~
.. list-table::
:header-rows: 1
:widths: 40 40 20
* - 配置项
- 说明
- 默认值
* - ``CONFIG_ACOMP``
- 启用ACOMP组件
- n
* - ``CONFIG_ACOMP_FD``
- 启用ACOMP组件的人脸识别组件
- n
资源配置
~~~~~~~~
.. list-table::
:header-rows: 1
:widths: 50 30 20
* - 配置项
- 说明
- 默认值
* - ``CONFIG_ACOMP_FD_RES_FACE_DETECT_ADDRESS``
- 人脸检测模型地址(Flash)
- 0x30100000
* - ``CONFIG_ACOMP_FD_RES_FACE_DETECT_LENGTH``
- 人脸检测模型长度
- 450936
* - ``CONFIG_ACOMP_FD_RES_FACE_ALIGN_ADDRESS``
- 人脸对齐模型地址(Flash)
- 0x30170000
* - ``CONFIG_ACOMP_FD_RES_FACE_ALIGN_LENGTH``
- 人脸对齐模型长度
- 1588664
* - ``CONFIG_ACOMP_FD_RES_FACE_LIVE_ADDRESS``
- 活体检测模型地址(Flash)
- 0x30300000
* - ``CONFIG_ACOMP_FD_RES_FACE_LIVE_LENGTH``
- 活体检测模型长度
- 1095288
* - ``CONFIG_ACOMP_FD_FACE_VERIFY_ADDRESS``
- 特征提取模型地址(Flash)
- 0x30410000
* - ``CONFIG_ACOMP_FD_FACE_VERIFY_LENGTH``
- 特征提取模型长度
- 2953752
快速开始
--------
1. 启用组件
~~~~~~~~~~~
在项目的 ``prj.conf`` 文件中添加:
.. code-block:: kconfig
# 启用 ACOMP 组件
CONFIG_ACOMP=y
# 启用ACOMP组件的FD组件
CONFIG_ACOMP_FD=y
# 配置人脸识别组件所需资源在flash的位置和大小
CONFIG_ACOMP_FD_RES_FACE_DETECT_ADDRESS=0x30100000
CONFIG_ACOMP_FD_RES_FACE_DETECT_LENGTH=450936
CONFIG_ACOMP_FD_RES_FACE_ALIGN_ADDRESS=0x30170000
CONFIG_ACOMP_FD_RES_FACE_ALIGN_LENGTH=1588664
CONFIG_ACOMP_FD_RES_FACE_LIVE_ADDRESS=0x30300000
CONFIG_ACOMP_FD_RES_FACE_LIVE_LENGTH=1095288
CONFIG_ACOMP_FD_FACE_VERIFY_ADDRESS=0x30410000
CONFIG_ACOMP_FD_FACE_VERIFY_LENGTH=2953752
2. 初始化人脸识别组件
~~~~~~~~~~~~~~~~~~~~~~
在应用程序中初始化人脸识别组件:
.. code-block:: c
#include "acomp.h"
#include "fd/acomp_fd.h"
int main(int argc, char **argv)
{
// 初始化 ACOMP 框架
acomp_init();
// 初始化人脸识别组件
int ret = acomp_fd_init();
if (ret != ACOMP_ERR_OK) {
printf("FD init failed: %d\n", ret);
return -1;
}
// 你的应用代码
return 0;
}
3. 注册事件回调
~~~~~~~~~~~~~~~
使用事件回调函数接收人脸识别结果:
.. code-block:: c
#include "fd/acomp_fd.h"
void fd_event_handler(uint32_t event, void *event_data,
uint32_t event_data_len, void *priv)
{
if (event & FD_CB_EVENT_ENGINE_RLT) {
// 人脸识别结果
acomp_fd_result_info_t *info = (acomp_fd_result_info_t *)event_data;
if (info->results_cnt > 0) {
uint32_t max_idx = info->max_area_results_index;
acomp_fd_result_t *result = &info->results[max_idx];
printf("Face detected: [%d,%d,%d,%d], score: %.2f\n",
result->face_rect.x, result->face_rect.y,
result->face_rect.w, result->face_rect.h,
result->face_score);
printf("Head pose: yaw=%.1f, pitch=%.1f, roll=%.1f\n",
result->pose.yaw, result->pose.pitch, result->pose.roll);
printf("Live detect: status=%d, score=%.2f\n",
result->live_result.status,
result->live_result.scores[1]);
} else {
printf("No face detected\n");
}
} else if (event & FD_CB_EVENT_ENGINE_WR_ERR) {
// 写入错误
printf("FD write error\n");
}
}
// 注册回调
int ret = acomp_fd_add_callback(
FD_CB_EVENT_ENGINE_RLT | FD_CB_EVENT_ENGINE_WR_ERR,
fd_event_handler,
NULL
);
4. 启动人脸识别服务
~~~~~~~~~~~~~~~~~~~
完整的启动流程:
.. code-block:: c
#include "fd/acomp_fd.h"
void start_fd_service(void)
{
int ret;
// 1. 就绪组件(分配资源)
ret = acomp_fd_prepare();
if (ret != ACOMP_ERR_OK) {
printf("FD prepare failed: %d\n", ret);
return;
}
// 2. 启动人脸识别
ret = acomp_fd_start();
if (ret != ACOMP_ERR_OK) {
printf("FD start failed: %d\n", ret);
return;
}
printf("FD service started\n");
}
void stop_fd_service(void)
{
int ret;
// 1. 停止人脸识别
ret = acomp_fd_stop();
if (ret != ACOMP_ERR_OK) {
printf("FD stop failed: %d\n", ret);
return;
}
// 2. 清理资源
ret = acomp_fd_cleanup();
if (ret != ACOMP_ERR_OK) {
printf("FD cleanup failed: %d\n", ret);
return;
}
printf("FD service stopped\n");
}
5. 配置活体检测参数
~~~~~~~~~~~~~~~~~~~
设置活体检测模式和阈值:
.. code-block:: c
#include "fd/acomp_fd.h"
void configure_live_detect(void)
{
// 配置活体检测
acomp_fd_live_detect_mode_t mode = {
.enable = true, // 启用活体检测
.score_threshold = {
0.51, // 假人阈值(未使用)
0.1, // 真人阈值(活体得分 >= 0.1 才进行特征提取)
},
};
int ret = acomp_fd_live_detect_mode_set(&mode);
if (ret != ACOMP_ERR_OK) {
printf("Set live detect mode failed: %d\n", ret);
}
}
6. 创建图像输入流并发送图像数据
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
使能 M2R (Master to Remote) 流通道,用于将图像数据发送给 AP 核:
.. code-block:: c
#include "fd/acomp_fd.h"
#define TX_STREAM_CH_INDEX 0
#define TX_STREAM_CH_NAME "stream.fd_image"
void setup_tx_stream(void)
{
// 1. 创建 M2R 流通道描述符
acomp_stream_chn_create_desc_t desc = {
.cname = TX_STREAM_CH_NAME,
.direction = ACOMP_STREAM_DIRECTION_M2R, // Master to Remote
.index = TX_STREAM_CH_INDEX,
.buffer_size = 320 * 240 * 2 + sizeof(acomp_fd_input_frame_t),
.num_descs = 4, // 缓冲区描述符数量
.kick_policy = 1, // 自动触发
};
// 2. 使能流通道
int ret = acomp_fd_stream_ch_enable(TX_STREAM_CH_INDEX, &desc);
if (ret != ACOMP_ERR_OK) {
printf("Failed to enable tx stream: %d\n", ret);
}
}
void send_image_to_fd(uint8_t *image_data, int width, int height,
acomp_fd_pixel_format format)
{
uint8_t *buffer;
uint32_t buf_size;
uint16_t desc_idx;
// 1. 分配发送缓冲区
buffer = acomp_fd_stream_tx_buffer_alloc(TX_STREAM_CH_INDEX,
&buf_size, &desc_idx);
if (buffer && buf_size > 0) {
// 2. 填充图像帧数据
acomp_fd_input_frame_t *frame = (acomp_fd_input_frame_t *)buffer;
frame->format = format;
frame->index = 0;
frame->width = width;
frame->height = height;
frame->length = width * height * 2; // YUYV422
memcpy(frame->data, image_data, frame->length);
// 3. 提交缓冲区发送
acomp_fd_stream_tx_buffer_submit(TX_STREAM_CH_INDEX,
buffer, buf_size, desc_idx);
}
}
7. 人脸特征管理
~~~~~~~~~~~~~~~
导入人脸特征用于识别:
.. code-block:: c
#include "fd/acomp_fd.h"
void load_face_features(void)
{
// 准备人脸特征数据(特征可从人脸识别组件识别结果或文件或数据库读取)
acomp_fd_feature_result_t features[3]; // 最多10个
// 假设已经从某处获取了特征数据(特征可从人脸识别组件识别结果或文件或数据库读取)
// load_features_from_storage(features, 3);
// 导入特征到人脸识别组件
int ret = acomp_fd_features_load(features, 3);
if (ret != ACOMP_ERR_OK) {
printf("Load features failed: %d\n", ret);
} else {
printf("Loaded 3 face features\n");
}
}
API 参考
--------
生命周期管理
~~~~~~~~~~~~
acomp_fd_init
^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_init(void);
**功能**:初始化人脸识别组件
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_NO_MEM``:内存不足
- ``ACOMP_ERR_INVALID_STATE``:无效状态
- ``ACOMP_ERR_NOT_FOUND``:设备未找到
acomp_fd_prepare
^^^^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_prepare(void);
**功能**:就绪人脸识别组件,初始化内存块及算法资源
**说明**:在调用 ``acomp_fd_start()`` 之前必须调用此函数
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_NO_MEM``:内存不足
- ``ACOMP_ERR_INVALID_STATE``:无效状态
acomp_fd_cleanup
^^^^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_cleanup(void);
**功能**:复位人脸识别组件,释放内存块及算法资源
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_INVALID_STATE``:无效状态
acomp_fd_start
^^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_start(void);
**功能**:启动人脸识别组件,开始处理图像流
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_NO_MEM``:内存不足
- ``ACOMP_ERR_INVALID_STATE``:无效状态
acomp_fd_stop
^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_stop(void);
**功能**:停止人脸识别组件,停止处理图像流
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_INVALID_STATE``:无效状态
参数配置
~~~~~~~~
acomp_fd_params_set
^^^^^^^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_params_set(const acomp_fd_param_t *params, uint32_t params_cnt);
**功能**:设置组件参数
**参数**
- ``params``:参数数组指针
- ``params_cnt``:参数个数
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_INVALID_ARG``:参数错误
- ``ACOMP_ERR_INVALID_STATE``:无效状态
acomp_fd_live_detect_mode_set
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_live_detect_mode_set(const acomp_fd_live_detect_mode_t *mode);
**功能**:设置活体检测模式
**参数**
- ``mode``:活体检测配置
- ``enable``:是否启用活体检测
- ``score_threshold[1]``:真人得分阈值(活体得分 >= 此值才进行特征提取)
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_INVALID_ARG``:参数错误
- ``ACOMP_ERR_INVALID_STATE``:无效状态
acomp_fd_align_threshold_set
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_align_threshold_set(const acomp_fd_head_pose_t *threshold);
**功能**:设置人脸对齐的头部姿态阈值
**说明**:如果头部姿态角度超过阈值,将不进行活体检测和特征提取
**参数**
- ``threshold``:头部姿态阈值
- ``yaw``:偏航角阈值
- ``pitch``:俯仰角阈值
- ``roll``:翻滚角阈值
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_INVALID_ARG``:参数错误
- ``ACOMP_ERR_INVALID_STATE``:无效状态
acomp_fd_features_load
^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_features_load(const acomp_fd_feature_result_t *features, uint32_t count);
**功能**:从外部导入人脸特征到注册库
**参数**
- ``features``:人脸特征数组指针
- ``count``特征个数最多10个
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_NO_MEM``:内存不足
- ``ACOMP_ERR_INVALID_ARG``:参数错误
- ``ACOMP_ERR_INVALID_STATE``:无效状态
事件回调
~~~~~~~~
acomp_fd_add_callback
^^^^^^^^^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_add_callback(uint32_t events, fd_event_cb_t cb, void *priv);
**功能**:添加事件回调函数
**参数**
- ``events``:事件位掩码,可同时注册多个事件
- ``FD_CB_EVENT_ENGINE_RLT``:人脸识别结果返回
- ``FD_CB_EVENT_ENGINE_WR_ERR``:算法引擎写入错误
- ``cb``:回调函数指针
- ``priv``:回调函数的私有数据指针
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_NO_MEM``:内存不足
- ``ACOMP_ERR_INVALID_ARG``:参数错误
- ``ACOMP_ERR_INVALID_STATE``:无效状态
acomp_fd_remove_callback
^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_remove_callback(fd_event_cb_t cb);
**功能**:移除回调函数
**参数**
- ``cb``:待移除的回调函数
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_INVALID_ARG``:参数错误
- ``ACOMP_ERR_INVALID_STATE``:无效状态
- ``ACOMP_ERR_NOT_SUPPORTED``:不支持的操作
图像流管理
~~~~~~~~~~
acomp_fd_stream_ch_enable
^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_stream_ch_enable(int chn, acomp_stream_chn_create_desc_t *desc);
**功能**:使能图像流通道
**参数**
- ``chn``:通道索引
- ``desc``:通道描述符指针
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_INVALID_STATE``:无效状态
- ``ACOMP_ERR_INVALID_ARG``:参数错误
- ``ACOMP_ERR_CREATE_STREAM_FAILED``:创建流失败
acomp_fd_stream_ch_disable
^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_stream_ch_disable(int chn);
**功能**:禁用图像流通道
**参数**
- ``chn``:通道索引
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_INVALID_STATE``:无效状态
- ``ACOMP_ERR_INVALID_ARG``:参数错误
acomp_fd_stream_tx_buffer_alloc
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: c
void* acomp_fd_stream_tx_buffer_alloc(int chn, uint32_t* len, uint16_t* desc_idx);
**功能**:分配 TX 流缓冲区用于向 AP 核发送图像数据
**参数**
- ``chn``:通道索引
- ``len``:可用缓冲区长度指针(输出)
- ``desc_idx``:描述符索引指针(输出)
**返回值**:缓冲区指针,失败返回 NULL
acomp_fd_stream_tx_buffer_submit
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: c
int acomp_fd_stream_tx_buffer_submit(int chn, void* buffer,
uint32_t len, uint16_t desc_idx);
**功能**:提交 TX 流缓冲区发送图像数据到 AP 核
**参数**
- ``chn``:通道索引
- ``buffer``:缓冲区指针
- ``len``:数据长度
- ``desc_idx``:描述符索引
**返回值**
- ``ACOMP_ERR_OK``:成功
- ``ACOMP_ERR_INVALID_STATE``:无效状态
- ``ACOMP_ERR_INVALID_ARG``:参数错误
使用示例
--------
完整示例
~~~~~~~~
.. code-block:: c
#include "acomp.h"
#include "fd/acomp_fd.h"
#include "lisa_log.h"
#define TAG "fd_demo"
// 事件回调函数
void fd_event_handler(uint32_t event, void *event_data,
uint32_t event_data_len, void *priv)
{
if (event & FD_CB_EVENT_ENGINE_RLT) {
acomp_fd_result_info_t *info = (acomp_fd_result_info_t *)event_data;
LISA_LOGI(TAG, "FD result: count=%d", info->results_cnt);
if (info->results_cnt > 0) {
uint32_t idx = info->max_area_results_index;
acomp_fd_result_t *result = &info->results[idx];
LISA_LOGI(TAG, "Face rect: [%d,%d,%d,%d], score: %.2f",
result->face_rect.x, result->face_rect.y,
result->face_rect.w, result->face_rect.h,
result->face_score);
LISA_LOGI(TAG, "Head pose: yaw=%.1f, pitch=%.1f, roll=%.1f",
result->pose.yaw, result->pose.pitch, result->pose.roll);
LISA_LOGI(TAG, "Live: status=%d, score=%.2f",
result->live_result.status,
result->live_result.scores[1]);
if (result->compare_cnt > 0) {
LISA_LOGI(TAG, "Compare scores: [%.2f, %.2f]",
result->compare_scores[0],
result->compare_scores[1]);
}
}
} else if (event & FD_CB_EVENT_ENGINE_WR_ERR) {
LISA_LOGE(TAG, "FD write error");
}
}
void fd_demo(void)
{
int ret;
// 1. 初始化 ACOMP 框架
acomp_init();
// 2. 初始化人脸识别组件
ret = acomp_fd_init();
if (ret != ACOMP_ERR_OK) {
LISA_LOGE(TAG, "FD init failed: %d", ret);
return;
}
// 3. 注册事件回调
ret = acomp_fd_add_callback(
FD_CB_EVENT_ENGINE_RLT | FD_CB_EVENT_ENGINE_WR_ERR,
fd_event_handler,
NULL
);
if (ret != ACOMP_ERR_OK) {
LISA_LOGE(TAG, "Add callback failed: %d", ret);
return;
}
// 4. 就绪组件
ret = acomp_fd_prepare();
if (ret != ACOMP_ERR_OK) {
LISA_LOGE(TAG, "FD prepare failed: %d", ret);
return;
}
LISA_LOGI(TAG, "FD prepared");
// 5. 启动人脸识别
ret = acomp_fd_start();
if (ret != ACOMP_ERR_OK) {
LISA_LOGE(TAG, "FD start failed: %d", ret);
return;
}
LISA_LOGI(TAG, "FD started");
// 6. 配置活体检测
acomp_fd_live_detect_mode_t mode = {
.enable = true,
.score_threshold = {0.51, 0.1},
};
acomp_fd_live_detect_mode_set(&mode);
// 7. 创建图像输入流
acomp_stream_chn_create_desc_t desc = {
.cname = "stream.fd_image",
.direction = ACOMP_STREAM_DIRECTION_M2R,
.index = 0,
.buffer_size = 320 * 240 * 2 + sizeof(acomp_fd_input_frame_t),
.num_descs = 4,
.kick_policy = 1,
};
acomp_fd_stream_ch_enable(0, &desc);
// 8. 发送图像数据(示例)
// send_image_to_fd(...);
// 9. 运行一段时间
vTaskDelay(pdMS_TO_TICKS(10000));
// 10. 停止人脸识别
ret = acomp_fd_stop();
if (ret != ACOMP_ERR_OK) {
LISA_LOGE(TAG, "FD stop failed: %d", ret);
}
LISA_LOGI(TAG, "FD stopped");
// 11. 清理资源
ret = acomp_fd_cleanup();
if (ret != ACOMP_ERR_OK) {
LISA_LOGE(TAG, "FD cleanup failed: %d", ret);
}
LISA_LOGI(TAG, "FD cleaned up");
}
图像流处理示例
~~~~~~~~~~~~~~
.. code-block:: c
#include "fd/acomp_fd.h"
void image_stream_tx_example(uint8_t *image_data, int width, int height)
{
int chn = 0;
uint32_t len;
uint16_t desc_idx;
void *buffer;
// 分配发送缓冲区
buffer = acomp_fd_stream_tx_buffer_alloc(chn, &len, &desc_idx);
if (buffer) {
// 填充图像帧数据
acomp_fd_input_frame_t *frame = (acomp_fd_input_frame_t *)buffer;
frame->format = PIX_FMT_YUV422_YUYV_PACKED;
frame->index = 0;
frame->width = width;
frame->height = height;
frame->length = width * height * 2;
memcpy(frame->data, image_data, frame->length);
// 提交发送
acomp_fd_stream_tx_buffer_submit(chn, buffer, len, desc_idx);
}
}
注意事项
--------
1. **初始化顺序**:必须先调用 ``acomp_init()`` 初始化 ACOMP 框架,再调用 ``acomp_fd_init()``
2. **生命周期管理**:启动前必须调用 ``acomp_fd_prepare()``,停止后应调用 ``acomp_fd_cleanup()`` 释放资源
3. **状态检查**:所有 API 都会进行状态检查,确保在正确的状态下调用相应的函数
4. **事件回调**:回调函数在组件内部线程中执行,应避免长时间阻塞操作
5. **内存管理**:组件使用动态内存分配,确保系统有足够的堆内存
6. **资源配置**:确保配置的模型地址和长度与实际烧录的模型匹配
7. **图像格式**:支持 YUYV422、RGB565、BGR888 等格式,推荐使用 YUYV422或RGB565 以节省内存
8. **活体检测阈值**:根据实际应用场景调整活体检测阈值,平衡误识率和拒识率
9. **特征管理**:最多支持 10 个注册人脸特征,每个特征为 384 维浮点数
10. **跨核通信**:图像流基于 IPC 机制,注意跨核数据传输的延迟和同步问题
11. **双核协作**:本组件运行在 CP 核,需要 AP 核提供算法支持,确保 AP 核固件正确烧录
常见问题
--------
**Q: 人脸识别组件初始化失败怎么办?**
A: 检查以下几点:
- 确保 ACOMP 框架已正确初始化
- 检查系统是否有足够的堆内存
- 确认 AP 核固件和算法模型已正确烧录到 Flash
**Q: 为什么没有检测到人脸?**
A: 可能的原因:
- 图像质量不佳(光线不足、模糊等)
- 人脸角度过大或遮挡严重
- 图像格式或尺寸不正确
- 检查回调函数是否正确注册
**Q: 活体检测总是失败怎么办?**
A: 建议:
- 调整活体检测阈值 ``score_threshold[1]`` (降低阈值更容易通过)
- 确保图像质量良好,光线充足
- 检查人脸是否正对摄像头,角度不要过大
**Q: 特征比对得分很低怎么办?**
A: 建议:
- 确保注册和识别时的图像质量一致
- 检查人脸角度和光线条件
- 特征比对阈值通常设置为 0.7-0.9,根据实际情况调整
**Q: 如何提高识别准确率?**
A: 建议:
- 使用高质量的图像输入(清晰、光线充足)
- 确保人脸正对摄像头,角度不要过大
- 注册多个角度的人脸特征
- 调整活体检测和特征比对阈值