当前位置: 首页 > news >正文

Linux58:rockx_vi_handle_thread线程的讲解

目录

1.本章节介绍

2.rockx_vi_handle_thread线程的流程框图

3.rockx_vi_handle_thread线程的代码截图

3.1. 初始化三个rockx模块

3.2. 读取每一帧VI数据并进行人脸检测

3.3. 对人脸数据过滤并且进行对齐识别

3.4. 遍历map容器的人脸数据并和当前RV1126的人脸数据进行相似度比较

扩展

1.迭代器

1.1、什么是迭代器?

1.2、迭代器的基本用法

1. begin() 是什么意思?

2. end() 是什么意思?

3. iter++ 是什么意思?

1.3、map 迭代器里的 first 和 second

1.4、iter->first 和 (*iter).first 是一样的

2.rockx_face_filte


1.本章节介绍

本章节主要介绍rockx_vi_handle_thread线程的工作流程,这个线程最主要的功能是获取第一个VI模块的视频数据,并且使用rockx的人脸检测模块、人脸识别模块、人脸关键点模块对视频流数据进行人脸识别,最后把识别的结果(包括人脸检测区域、人脸识别名称)保存到全局变量里面。

2.rockx_vi_handle_thread线程的流程框图

上图是rockx_vi_handle_thread线程的工作流程。首先要初始化三个rockx模块,分别是人脸检测模块、人脸识别模块、人脸关键点检测模块。然后获取ROCKX的VI模块数据,然后调用rockx_face_detect检测VI数据的人脸区域数据,并保存到全局变量。并判断VI数据是否有人脸,若有人脸则使用rockx_face_filter过滤人脸。

若过滤到人脸,则调用rockx_face_recognize对RV1126视频人脸进行识别并且提取特征值。然后遍历Map容器的人脸特征值,并且和当前RV1126视频的人脸特征值进行相似度对比,使用的是rockx_face_feature_similarity,若相似度<=1.1则认定为同一个人,并从Map里面通过人脸特征值获取名字,否则就不处理。

3.rockx_vi_handle_thread线程的代码截图

3.1.初始化三个rockx模块

这段代码是初始化rockx的三个模块,首先要使用rockx_create_config分配rockx_config_t结构体,并使用rockx_add_config把对应的rockx路径配置进去,在我们的板子里面在/userdata/rockx_data里面,并使用rockx_create创建三个rockx_handle_t句柄,分别是face_det_handle(人脸检测模块)face_recognize_handle(人脸识别模块)face_5landmarks_handle(人脸关键点模块)

3.2.读取每一帧VI数据并进行人脸检测

初始化rockx_image_t结构体,初始化需要传三个值分别是width = WIDTH(1920)、height = HEIGHT(1080)、pixel_format=ROCKX_PIXEL_FORMAT_YUV420SP_NV12。这三个值都需要和VI模块的配置是一样的。

初始化rockx_image_t后,则需要通过RK_MPI_SYS_GetMediaBuffer获取每一帧VI模块的数据,并把每一帧VI模块的缓冲区和长度传输给rockx_image_t。具体的代码是rv1126_rockx_image.data = (uint8_t *)RK_MPI_MB_GetPtr(mb)(把每一帧VI缓冲区数据赋值到rockx_image_t的data)、rv1126_rockx_image.size = RK_MPI_MB_GetSize(mb)(把每一帧VI大小赋值到rockx_image_t的size)

赋值到rockx_image_t则调用rockx_face_detect对每一帧的rockx_image_t图像进行人脸检测,并把人脸检测的结果输出到rockx_object_array_trockx_object_array_t的内容主要存储的是人脸检测数量和人脸检测区域信息,并调用set_rockx_face_arrayrockx_object_array_t设置到全局变量。

3.3.对人脸数据过滤并且进行对齐识别

若人脸检测的数量大于0,则认为成功检测到人脸。就对每一帧RV1126图像的人脸图像进行过滤,使用的API是rockx_face_filter过滤完人脸之后,就通过rockx_face_align进行对齐,最后进行人脸识别提取人脸特征值,使用的API是rockx_face_recognize

3.4.遍历map容器的人脸数据并和当前RV1126的人脸数据进行相似度比较

这一步是遍历map容器的所有数据,找出所有的value人脸特征值,其中key存储的是人脸的名称,value存储的是人脸特征值。然后通过rockx_face_feature_similarity(&database_iter->second,&rv1126_feature, &similarity)去逐一对比map容器的人脸特征值和当前RV1126的人脸特征值。database_iter->second指的是Map容器里面的人脸特征值,rv1126_feature指的是RV1126视频流的人脸特征值。

若对比的相似度<=1.0,则代表同一个人,并找出这个人脸特征对应的名字,在Map容器是KEY值。找到名字后,则把名字设置到全局变量里面set_rockx_people。下面是map容器查找和RV1126视频流匹配的图解,它是通过RV1126的人脸特征值和Map的人脸特征值进行对比,然后通过value获取KEY的值。

扩展

1.迭代器

解析:这里的效果是,创建一个类来获取全局的0号 s_thread_map ,然后把map容器拷贝给 database_face_map 方便进行遍历,database_iter 是一个迭代器,用来遍历容器,比对人脸特征

1.1、什么是迭代器?

迭代器可以理解成:容器里的一个“游标”

它用来指向容器中的某一个元素。

比如你有一个容器:

map<string, int> scores; scores["zhangsan"] = 90; scores["lisi"] = 80; scores["wangwu"] = 70;

这个map里面有三条数据:

"zhangsan" -> 90 "lisi" -> 80 "wangwu" -> 70

如果你想一个一个访问它们,就需要一个东西来“指向当前访问到哪一项”。

这个东西就是迭代器:

map<string, int>::iterator iter;

iter就像一个指针,刚开始可以指向第一项,然后移动到第二项、第三项。

1.2、迭代器的基本用法

最常见的写法是:

map<string, int>::iterator iter; for (iter = scores.begin(); iter != scores.end(); iter++) { cout << iter->first << " = " << iter->second << endl; }

这段代码会遍历整个scores

1.begin()是什么意思?

scores.begin()

表示指向容器的第一个元素

比如:

iter = scores.begin();

意思是:让iter指向scores里面的第一条数据。

2.end()是什么意思?

scores.end()

表示容器的结束位置

注意,end()不是最后一个元素,它是“最后一个元素的后面”。

可以这样理解:

[zhangsan] [lisi] [wangwu] [end]

所以遍历时要写:

iter != scores.end()

意思是:只要还没有走到末尾,就继续循环。

不能访问end()

下面这样是错误的:

iter = scores.end(); cout << iter->first << endl; // 错误

因为end()不指向有效元素。

3.iter++是什么意思?

iter++

表示让迭代器移动到下一个元素。

1.3、map迭代器里的firstsecond

map的每一项都是一对数据:

key -> value

在 C++ 里,这一对数据叫做pair

对于:

map<string, int> scores;

每一个元素可以理解成:

pair<string, int>

里面有两个成员:

first second

其中:

iter->first

表示 key。

iter->second

表示 value。

例如:

map<string, int> scores; scores["zhangsan"] = 90; scores["lisi"] = 80; scores["wangwu"] = 70; map<string, int>::iterator iter; for (iter = scores.begin(); iter != scores.end(); iter++) { cout << "name = " << iter->first << endl; cout << "score = " << iter->second << endl; }

输出逻辑就是:

name = zhangsan score = 90 name = lisi score = 80 name = wangwu score = 70

1.4、iter->first(*iter).first是一样的

迭代器有点像指针。

所以这两种写法等价:

iter->first

和:

(*iter).first

同理:

iter->second

等价于:

(*iter).second

但是一般都写:

iter->first iter->second

更简单。

2.rockx_face_filte

函数的定义:这个API主要是过滤人脸,过滤图像中不符合人脸的图像

rockx_ret_t rockx_face_filter(rockx_handle_t handle, rockx_image_t *in_img, rockx_rect_t *in_box, int *is_false_face);

第一个参数:rockx_handle_t的结构体

第二个参数:in_img是输入的图像

第三个参数:in_box人脸检测区域,是一个矩形

第四个参数:is_falas_face判断当前检测的图像是否是人脸,是人脸就等于true,否则false

http://www.jsqmd.com/news/824081/

相关文章:

  • 如何用免费开源工具彻底替代Dell G15的AWCC:终极散热控制指南
  • Android自动化测试代理droidrun-agent:原理、实现与工程实践
  • 2026年5月比较好的回收石墨/石墨回收厂家推荐临漳县福鑫碳素有限公司 - 品牌鉴赏师
  • 低功耗时序电路设计:约翰逊计数器与时钟门控技术优化
  • 智能助手会话上下文管理:基于向量检索的长期记忆与多技能协作实践
  • 保姆级教程:用Vissim从零搭建一个真实路口路网(附底图比例尺校准技巧)
  • 老旧主板救星记:手把手教你诊断华硕H81M-CT的USB过流保护故障
  • 星恒讯5G工业级通信模组选型指南:接口配置、工业防护与应用场景详解
  • 基于Lobe与树莓派的边缘AI包裹检测系统:从模型训练到自动化通知
  • 英飞凌PSoC 6开发环境搭建:ModusToolbox从安装到Hello World实战
  • 宇树科技校招怎么准备:别只会讲具身智能,真机运动控制和软硬结合才是主线
  • 基于AI编程前沿技术,主题为变形金刚:手脑协同 + 触发指令 + AI大数据落地系统,目前落地解决方案
  • Java程序员什么时候要深入学习JVM底层原理?
  • 零门槛云端实时物体识别:基于Google Colab与MobileNet V2的实践指南
  • 星恒讯4G工业级无线数传模组选型指南:接口、环境适配与典型应用场景
  • 数字信号频谱分析实战:从混叠、泄漏到窗函数与平均技术
  • 守护进程Guardian:轻量级进程保活与高可用架构实践
  • 48_《智能体微服务架构企业级实战教程》智能助手主应用服务之工具决策节点
  • 基于MCP协议构建递归认知市场:多智能体协作与去中心化AI新范式
  • Node.js权限管理实战:基于Guardian的策略模式与轻量级授权方案
  • CUA Desktop Operator:为AI智能体提供Windows桌面自动化能力
  • 从D触发器到Latch:深入芯片底层,图解Timing Borrow如何‘偷’出时钟周期
  • 5分钟实现PNG/JPG到SVG的终极转换:vectorizer矢量化工具完全指南
  • 如何用PDF Arranger轻松解决PDF页面管理难题:完整指南
  • Nooploop TOFSense激光测距模块:从快速上手指南到多平台实战应用
  • 【HarmonyOS 6.1 全场景实战】《灵犀厨房》实战之补充【架构进化】灵犀厨房四层分层设计:给鸿蒙 App 搭一副坚不可摧的骨架
  • 从大语言模型到文本检测:Awesome资源清单与实战指南
  • 基于GitHub Actions与OpenAI API构建AI自动编程工作流实践
  • 用Arduino和MAX7219点亮你的第一个8x8 LED点阵屏(附完整代码与接线图)
  • AbMole丨Apigenin:天然黄酮化合物在氧化应激中的应用