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_t。rockx_object_array_t的内容主要存储的是人脸检测数量和人脸检测区域信息,并调用set_rockx_face_array把rockx_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迭代器里的first和second
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 = 701.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
