Linux_58:rockx_vi_handle_thread线程详解
目录
-
本章概述
-
rockx_vi_handle_thread线程流程图
-
rockx_vi_handle_thread线程源码分析
3.1. 初始化rockx模块
3.2. 获取VI帧数据并执行人脸检测
3.3. 人脸数据筛选与对齐识别
3.4. 与数据库人脸特征比对
扩展
- 迭代器概念
1.1. 迭代器的定义
1.2. 迭代器基本操作
1.3. map容器迭代器的first和second
1.4. iter->first与(*iter).first的区别
-
rockx_face_filter函数说明
-
线程参数传递机制
1. 本章概述
本章重点讲述rockx_vi_handle_thread线程的工作机制。该线程负责从VI模块获取视频流数据,并利用rockx库中的人脸检测、人脸识别及关键点检测功能进行实时人脸识别处理,最终将识别结果(包含人脸框坐标与识别标签)存入共享内存供其他模块使用。
2. rockx_vi_handle_thread线程流程图

如图所示,rockx_vi_handle_thread线程首先初始化三个核心模块:人脸检测、人脸识别以及关键点检测。随后,通过获取VI模块的视频帧数据,调用rockx_face_detect进行人脸定位,并将结果保存至全局变量。当检测到人脸时,进一步调用rockx_face_filter进行过滤处理。



经过过滤后,使用rockx_face_recognize完成人脸识别并提取特征。接着遍历已有的特征库,通过rockx_face_feature_similarity计算相似度,若低于阈值则判定为同一人,并根据特征值查找对应姓名,更新全局状态。
3. rockx_vi_handle_thread线程源码分析
3.1. 初始化rockx模块

此部分代码用于创建三个rockx句柄:
- face_det_handle(人脸检测)
- face_recognize_handle(人脸识别)
- face_5landmarks_handle(关键点检测)
初始化过程包括分配rockx_config_t结构体、添加配置路径(位于/userdata/rockx_data),并通过rockx_create生成各模块句柄。
3.2. 获取VI帧并执行人脸检测


先初始化rockx_image_t结构体,设置宽高及像素格式为NV12。然后通过RK_MPI_SYS_GetMediaBuffer获取VI帧数据,并填充至rockx_image_t结构中。最后调用rockx_face_detect进行人脸检测,返回结果保存到face_array中,并通过set_rockx_face_array将其设为全局变量供其他线程读取。
// 执行人脸检测
rockx_ret = rockx_face_detect(face_det_handle, &input_image, &face_array, NULL);
if (rockx_ret != ROCKX_RET_SUCCESS)
{
printf("rockx_face_detect ERROR %d\n", rockx_ret);
}
set_rockx_face_array(face_array);
此段代码实现了跨线程数据共享机制,使得show_vi_thread能获取并绘制人脸框。
3.3. 人脸数据筛选与对齐识别

若检测到人脸,则调用rockx_face_filter进行筛选,再使用rockx_face_align进行对齐,最终调用rockx_face_recognize提取特征值。
3.4. 特征比对与身份识别

遍历数据库中的所有特征值,逐一与当前帧的人脸特征比较。若相似度≤1.0,则认为是同一个人,从map中获取其名称并更新全局状态。

扩展
- 迭代器

示例代码展示了如何遍历map容器:
map<string, vector<float>> database_face_map;
map<string, vector<float>>::iterator database_iter;
for(database_iter = database_face_map.begin();
database_iter != database_face_map.end();
database_iter++)
{
// 比较特征值
float similarity;
rockx_face_feature_similarity(&(database_iter->second), &rv1126_feature, &similarity);
}
1.1、迭代器的含义
迭代器可视为容器内的"指针",用于遍历元素。
1.2、迭代器基本操作
常用方式如下:
map<string, int>::iterator iter;
for(iter = scores.begin(); iter != scores.end(); iter++)
{
cout << iter->first << " = " << iter->second << endl;
}
begin()返回指向首元素的迭代器end()返回指向末尾的迭代器(不指向实际元素)iter++移动到下一元素
1.3、map迭代器的first和second
每个map元素由键值对构成,first为key,second为value。
map<string, int> scores;
scores["zhangsan"] = 90;
// iter->first = "zhangsan"
// iter->second = 90
1.4、iter->first与(*iter).first等效
两种写法功能一致,推荐使用iter->first更简洁。
- rockx_face_filter函数说明
函数原型:
rockx_ret_t rockx_face_filter(rockx_handle_t handle, rockx_image_t *in_img, rockx_rect_t *in_box, int *is_false_face);
功能:用于过滤图像中非人脸区域,返回是否为真实人脸。
- 线程参数传递机制
pthread_t pid;
VI_PROC_PARAM * vi_arg_params = (VI_PROC_PARAM *)malloc(sizeof(VI_PROC_PARAM));
vi_arg_params->viId = 0; // 设置VI通道编号
pthread_create(&pid, NULL, rockx_vi_handle_thread, (void *)vi_arg_params);
线程内部接收参数:
VI_PROC_PARAM vi_arg = *(VI_PROC_PARAM *)args;
free(args);
src_mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VI, vi_arg.viId, -1);
这样可根据不同VI通道采集数据。