瑞芯微RV1126——人脸识别源码分析

本节内容主要分为3部分,第一部分是流程结构图;第二部分为人脸识别代码流程;第三部分为具体的代码分析。

1.流程结构图

2.人脸识别代码流程

1、人脸数据的初始化:

init_all_rockx_face_data();init_face_data();

2、创建rtsp会话,这里包括发送码流数据,得客户端,也就是我们在windows上用ffplay去拉流得时候,才会发送码流数据给客户端:

create_rtsp_demo(554);
rtsp_new_session
rtsp_set_video
rtsp_sync_video_ts

**
3、初始化vi通道属性**

 VI_CHN_ATTR_S vi_chn_attr;

4、初始化视频处理属性

RGA_ATTR_S stRgaAttr;

5、初始化编码通道属性:

VENC_CHN_ATTR_S venc_chn_attr;

6、绑定数据源:

RK_MPI_SYS_Bind

7、开始捕获码流:

RK_MPI_VI_StartStream

8、执行三个对应的线程:

  • pthread_create(&rockx_pid, NULL, rockx_vi_detect_thread, NULL);
  • pthread_create(&venc_pid, NULL, rockx_vi_face_recognize_venc_thread, NULL);
  • pthread_create(&rtsp_pid, NULL, rockx_venc_rtsp_thread, NULL);

**9、销毁申请的系统资源; **

3.核心代码分析

初始化vi通道属性;初始化视频处理属性;初始化编码通道属性;绑定数据源;开始捕获码流:

//初始化vi通道属性VI_CHN_ATTR_S vi_chn_attr;vi_chn_attr.pcVideoNode = pDeviceName;vi_chn_attr.u32BufCnt = u32BufCnt;vi_chn_attr.u32Width = u32Width;vi_chn_attr.u32Height = u32Height;//你的摄像头分辨率大小不要超过vencvi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;vi_chn_attr.enBufType = VI_CHN_BUF_TYPE_MMAP;vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;ret = RK_MPI_VI_SetChnAttr(s32CamId, 0, &vi_chn_attr);//设置vi通道属性ret |= RK_MPI_VI_EnableChn(s32CamId, 0);//使能vi通道属性,让其生效if (ret){printf("ERROR: create rkisp0 VI[0] error! ret=%d\n", ret);return 0;}//初始化rga属性RGA_ATTR_S stRgaAttr;stRgaAttr.bEnBufPool = RK_TRUE;stRgaAttr.u16BufPoolCnt = 2;stRgaAttr.u16Rotaion = 0;stRgaAttr.stImgIn.u32X = 0;stRgaAttr.stImgIn.u32Y = 0;stRgaAttr.stImgIn.imgType = IMAGE_TYPE_NV12;stRgaAttr.stImgIn.u32Width = u32Width;stRgaAttr.stImgIn.u32Height = u32Height;stRgaAttr.stImgIn.u32HorStride = u32Width;stRgaAttr.stImgIn.u32VirStride = u32Height;stRgaAttr.stImgOut.u32X = 0;stRgaAttr.stImgOut.u32Y = 0;stRgaAttr.stImgOut.imgType = IMAGE_TYPE_NV12;stRgaAttr.stImgOut.u32Width = disp_width;stRgaAttr.stImgOut.u32Height = disp_height;stRgaAttr.stImgOut.u32HorStride = disp_width;stRgaAttr.stImgOut.u32VirStride = disp_height;ret = RK_MPI_RGA_CreateChn(0, &stRgaAttr);//rga通道if (ret){printf("ERROR: Create rga[0] falied! ret=%d\n", ret);return -1;}//初始化编码属性VENC_CHN_ATTR_S venc_chn_attr;memset(&venc_chn_attr, 0, sizeof(VENC_CHN_ATTR_S));venc_chn_attr.stVencAttr.u32PicWidth = disp_width;venc_chn_attr.stVencAttr.u32PicHeight = disp_height;venc_chn_attr.stVencAttr.u32VirWidth = disp_width;venc_chn_attr.stVencAttr.u32VirHeight = disp_height;venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;venc_chn_attr.stVencAttr.u32Profile = 66;venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;//恒定的编码码率类型venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 30;venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = disp_width * disp_height * 3;venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 25;venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1;venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 25;ret = RK_MPI_VENC_CreateChn(0, &venc_chn_attr);//创建编码通道if (ret){printf("ERROR: Create venc failed!\n");exit(0);}//初始化mpp通道MPP_CHN_S vi_chn;MPP_CHN_S rga_chn;vi_chn.enModId = RK_ID_VI;vi_chn.s32ChnId = 0;rga_chn.enModId = RK_ID_RGA;rga_chn.s32ChnId = 0;ret = RK_MPI_SYS_Bind(&vi_chn, &rga_chn);//绑定vi和rga通道if (ret != 0){printf("[VI] vi id: %d bind venc id: %d, ret: %d error\n", vi_chn.s32ChnId, rga_chn.s32ChnId, ret);return -1;}

初始化三个线程

  //初始化三个线程idpthread_t rockx_pid;pthread_t venc_pid;pthread_t rtsp_pid;//创建人脸检测线程pthread_create(&rockx_pid, NULL, rockx_vi_detect_thread, NULL);//人脸识别线程pthread_create(&venc_pid, NULL, rockx_vi_face_recognize_venc_thread, NULL);//人脸编码rtsp传输线程pthread_create(&rtsp_pid, NULL, rockx_venc_rtsp_thread, NULL);

人脸检测线程

void *rockx_vi_detect_thread(void *args)
{//自动释放线程资源pthread_detach(pthread_self());//创建一个类对象thread_mapS_THREAD_MAP thread_map;//对thread_map进行初始化get_thread_map(0, &thread_map);//定义了一个map类型database_face_map对象map<string, rockx_face_feature_t> database_face_map = thread_map.thread_map;//定义迭代器database_itermap<string, rockx_face_feature_t>::iterator database_iter;//定义一个缓冲区MEDIA_BUFFER src_mb = NULL;//人脸模式枚举变量定义rockx_module_t data_version;data_version = ROCKX_MODULE_FACE_DETECTION_V2;//定义一个人脸执行返回结果变量rockx_ret_t rockx_ret;//定义人脸检测处理指针变量rockx_handle_t face_det_handle;//定义人脸识别特征提取处理指针变量rockx_handle_t face_recognize_handle;//定义人脸特征点定位处理指针变量rockx_handle_t face_5landmarks_handle;//定义了人脸标记检测处理指针变量rockx_handle_t face_masks_det_handle;//定义人脸配置结构体指针变量rockx_config_t *config = rockx_create_config();//获取人脸配置值//添加配置人脸模型存放路径,这里是存放在共享目录下:/mnt/nfs/rockx_data/rockx_add_config(config, ROCKX_CONFIG_DATA_PATH, "/mnt/nfs/rockx_data/");//创建使用人脸模型数据,来处理人脸检测rockx_ret = rockx_create(&face_det_handle, data_version, config,sizeof(rockx_config_t));//判断是否创建使用人脸模型数据 来处理人脸检测是否成功                         if (rockx_ret != ROCKX_RET_SUCCESS){printf("init face_detect error %d\n", rockx_ret);return NULL;}//使用人脸模型数据来人脸识别特征提取rockx_ret = rockx_create(&face_recognize_handle, ROCKX_MODULE_FACE_RECOGNIZE,config, sizeof(rockx_config_t));//识别是否成功                         if (rockx_ret != ROCKX_RET_SUCCESS){printf("init face_recognize error %d\n", rockx_ret);return NULL;}//使用模型算法数据来做人脸特征点定位处理rockx_ret = rockx_create(&face_5landmarks_handle,ROCKX_MODULE_FACE_LANDMARK_5, config, 0);//判断是否处理成功                         if (rockx_ret != ROCKX_RET_SUCCESS){printf("init rockx module ROCKX_MODULE_FACE_LANDMARK_68 error %d\n",rockx_ret);}// rockx_handle_t face_masks_det_handle;进行标记处理rockx_ret = rockx_create(&face_masks_det_handle,ROCKX_MODULE_FACE_MASKS_DETECTION, config, 0);if (rockx_ret != ROCKX_RET_SUCCESS){printf("init rockx module ROCKX_MODULE_FACE_MASKS_DETECTION error %d\n",rockx_ret);}//定义人脸图片结构体变量,并进行成员赋值rockx_image_t input_image;input_image.width = 1920;input_image.height = 1080;input_image.pixel_format = ROCKX_PIXEL_FORMAT_YUV420SP_NV12;bool is_recognize = false;string predict = "";//rockx_face_result_t face_result;int ret;//做轮询操作while (!quit){
#if 1//从指定通道中获取数据缓冲区src_mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VI, 0, -1);if (!src_mb){printf("ERROR: RK_MPI_SYS_GetMediaBuffer get null buffer!\n");break;}//从指定的MEDIA_BUFFER中获取缓冲区数据大小input_image.size = RK_MPI_MB_GetSize(src_mb);input_image.data = (unsigned char *)RK_MPI_MB_GetPtr(src_mb);//从指定的MEDIA_BUFFER中获取缓冲区数据指针
#endif#if 1//rockx_face_result_group_t face_result_group;//memset(&face_result_group, 0, sizeof(face_result_group));//定义人脸处理结果结构体变量rockx_object_array_t face_array;memset(&face_array, 0, sizeof(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);//判断检测人脸特征数量值是否大于0if (face_array.count > 0){//rockx_queue->putRockxFaceArray(face_array);printf("face_count : %d\n", face_array.count);for (int i = 0; i < face_array.count; i++){if (1){int is_false_face;//进行人脸过滤处理ret = rockx_face_filter(face_5landmarks_handle, &input_image,&face_array.object[i].box, &is_false_face);if (ret != ROCKX_RET_SUCCESS){printf("rockx_face_filter error %d\n", ret);}if (is_false_face)continue;}
#if 1//人脸检测结果(包括人脸、车牌、头部、物体等)变量定义rockx_object_t max_face;rockx_object_t cur_face = face_array.object[i];//进行人脸区域计算处理操作int cur_face_box_area = (cur_face.box.right - cur_face.box.left) *(cur_face.box.bottom - cur_face.box.top);int max_face_box_area = (max_face.box.right - max_face.box.left) *(max_face.box.bottom - max_face.box.top);if (cur_face_box_area > max_face_box_area){max_face = cur_face;}//检测输出处理rockx_image_t out_img;memset(&out_img, 0, sizeof(rockx_image_t));//进行面部矫正对齐ret = rockx_face_align(face_5landmarks_handle, &input_image,&(max_face.box), NULL, &out_img);if (ret != ROCKX_RET_SUCCESS){printf("face_align failed\n");}//人脸特征结果变量定义rockx_face_feature_t out_feature;//获取人脸特征rockx_face_recognize(face_recognize_handle, &out_img, &out_feature);for (database_iter = database_face_map.begin();database_iter != database_face_map.end(); database_iter++){float similarity;//比较两个人脸特征的相似性ret = rockx_face_feature_similarity(&database_iter->second,&out_feature, &similarity);printf("simple_value = %lf\n", similarity);//判断预测精度if (similarity <= 1.0){is_recognize = true;//predict_name_bak = database_iter->first;predict = database_iter->first;break;}else{is_recognize = false;predict = "";continue;}}if (is_recognize == true){predict = database_iter->first;}else{predict = "";}set_rockx_prdict_name(predict);#endif}}
#endif//释放缓冲区RK_MPI_MB_ReleaseBuffer(src_mb);src_mb = NULL;}//释放相关人脸处理数据模块rockx_destroy(face_det_handle);rockx_destroy(face_recognize_handle);rockx_destroy(face_5landmarks_handle);return NULL;
}

人脸识别线程

void *rockx_vi_face_recognize_venc_thread(void *args)
{pthread_detach(pthread_self());//线程资源自动释放MEDIA_BUFFER mb = NULL; //媒体缓存区int ret;float x_rate = (float)1280 / 1920;float y_rate = (float)720 / 1080;while (!quit){//从指定通道中获取数据缓冲区mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_RGA, 0, -1);if (!mb){printf("ERROR: RK_MPI_SYS_GetMediaBuffer get null buffer!\n");break;}//获取人脸处理结果rockx_object_array_t face_array = get_rockx_face_array();//创建mat对象,并创建了720x1080的像素块,每个像素每个通道的位数都是8位,一个字节的。上述CV_8UC3中的8表示8位、UC表示uchar类型、1表示1个通道Mat tmp_img = Mat(720, 1280, CV_8UC1, RK_MPI_MB_GetPtr(mb));
#if 1//对人脸x,y,w,h进行处理for (int i = 0; i < face_array.count; i++){int x = face_array.object[i].box.left * x_rate;int y = face_array.object[i].box.top * y_rate;int w = (face_array.object[i].box.right - face_array.object[i].box.left) * x_rate;int h = (face_array.object[i].box.bottom - face_array.object[i].box.top) * y_rate;if (x < 0)x = 0;if (y < 0)y = 0;while ((uint32_t)(x + w) >= 1280){w -= 16;}while ((uint32_t)(y + h) >= 720){h -= 16;}//获取人脸预测名字string predict_name = get_rockx_prdict_name();printf("predict_name = %s\n", predict_name.c_str());nv12_border((char *)RK_MPI_MB_GetPtr(mb), 1280, 720, x, y, w, h, 255, 0, 255);int baseline;//计算人脸名字文本大小Size text_size = getTextSize(predict_name, 2, 2, 2, &baseline);Point origin;origin.x = tmp_img.cols / 4 - text_size.width / 4;origin.y = tmp_img.rows / 4 + text_size.height / 4;//把名字字符填充到文本框里面去cv::putText(tmp_img, predict_name, origin, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 0, 255), 3);}
#endif//释放对应的资源RK_MPI_SYS_SendMediaBuffer(RK_ID_VENC, 0, mb);RK_MPI_MB_ReleaseBuffer(mb);mb = NULL;}return NULL;
}

人脸编码rtsp传输线程

void *rockx_venc_rtsp_thread(void *args)
{pthread_detach(pthread_self());MEDIA_BUFFER mb = NULL;while (!quit){mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, 0, -1);if (!mb){printf("ERROR: RK_MPI_SYS_GetMediaBuffer get null buffer!\n");break;}//rtsp来传输码流rtsp_tx_video(g_rtsp_session, (unsigned char *)RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb), RK_MPI_MB_GetTimestamp(mb));RK_MPI_MB_ReleaseBuffer(mb);rtsp_do_event(g_rtsplive);}return NULL;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/14885.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一个典型的分布式缓存系统是什么样的?no.32

分布式 Redis 服务 由于本课程聚焦于缓存&#xff0c;接下来&#xff0c;我将以微博内的 分布式 Redis 服务系统为例&#xff0c;介绍一个典型的分布式缓存系统的组成。 微博的 Redis 服务内部也称为 RedisService。RedisService 的整体架构如图所示。主要分为Proxy、存储、集…

产品推荐 | 基于Xilinx XCKU115的半高PCIe x8 硬件加速卡

一、板卡概述 本板卡系我公司自主研发&#xff0c;采用Xilinx公司的XCKU115-3-FLVF1924-E芯片作为主处理器&#xff0c;主要用于FPGA硬件加速。板卡设计满足工业级要求。如下图所示&#xff1a; 二、功能和技术指标 板卡功能 参数内容 主处理器 XCKU115-3-FLVF1924-E 板卡…

UE4/UE5像素流送云推流:多人访问不稳定、画面糊、端口占用多等

UE4/UE5想要实现网页访问&#xff0c;很多工程师会选择guan方的像素流送。但这个技术要求在模型开发初期就接入。对于一些已有UE模型是无法进行流化的。虽然也可以解决新UE模型的网页访问问题&#xff0c;但在实际的应用中&#xff0c;点量云流也收到很多反馈说&#xff0c;使用…

Python爬取B站视频:封装一下

&#x1f4da;博客主页&#xff1a;knighthood2001 ✨公众号&#xff1a;认知up吧 &#xff08;目前正在带领大家一起提升认知&#xff0c;感兴趣可以来围观一下&#xff09; &#x1f383;知识星球&#xff1a;【认知up吧|成长|副业】介绍 ❤️如遇文章付费&#xff0c;可先看…

大数据Hadoop之-工具HIVE(一)

大数据Hadoop之——数据仓库Hive HIVE介绍Hive是基于Hadoop的一个数据仓库(Data Aarehouse,简称数仓、DW),可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能。是用于存储、分析、报告的数据系统。 在Hadoop生态系统中,HDFS用于存储数据,Yarn用于资源管理…

【Linux】中的常见的重要指令(中)

目录 一、man指令 二、cp指令 三、cat指令 四、mv指令 五、more指令 六、less指令 七、head指令 八、tail指令 一、man指令 Linux的命令有很多参数&#xff0c;我们不可能全记住&#xff0c;我们可以通过查看联机手册获取帮助。访问Linux手册页的命令是 man 语法: m…

白嫖免费图床!CloudFlare R2太香了!

1 为啥要折腾搭建一个专属图床&#xff1f; 技术大佬写博客都用 md 格式&#xff0c;要在多平台发布&#xff0c;图片就得有外链后续如博客迁移&#xff0c;国内博客网站如掘金&#xff0c;简书&#xff0c;语雀等都做了防盗链&#xff0c;图片无法迁移 2 为啥选择CloudFlare…

对话太医管家CEO徐晶:数字化技术正在为健康管理行业带来新平衡丨数字思考者50人...

ITValue 钛媒体特别专题策划《数字思考者50人》&#xff1a;探访中国深刻的数字化思考者群体。我们理解的“TechThinker”&#xff0c;涵盖了中国数字化浪潮中的技术践行者、政策制定者与投资决策者。在这场长达10年的乘风破浪中&#xff0c;每个人都在分享技术进步的果实&…

文件系统--软硬链接

文章目录 现象软链接硬链接 现象 建立软链接 建立硬链接 // 删除软硬链接都可以用 unlink 指令 unlink soft-link软链接 软链接是一个独立的文件&#xff0c;因为有独立的inode number 软链接的内容&#xff1a;目标文件所对应的路劲字符串如果我们直接查看软链接文件&#…

vue2vue3为什么el-table树状表格失效?

上图所示&#xff0c;后端返回字段中有hasChildren字段。 解决树状表格失效方案&#xff1a; 从后端拿到数据后&#xff0c;递归去掉该字段&#xff0c;然后就能正常显示。&#xff08;复制下方代码&#xff0c;直接用&#xff09; 亲测有效&#xff0c;vue2、vue3通用 /**…

如何运用多媒体,打造企业实力展示厅?

企业文化、产品是其长期发展的根本所在&#xff0c;为此越来越多的企业开始选择运用多媒体互动&#xff0c;来打造企业多媒体展厅的方式&#xff0c;对企业文化、品牌形象、产品进行推广宣传&#xff0c;并在多媒体互动装置的支持下&#xff0c;能让客户能够快速且全面的了解企…

基于SSM的“酒店管理系统”的设计与实现(源码+数据库+文档)

基于SSM的“酒店管理系统”的设计与实现&#xff08;源码数据库文档) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 首页 管理员登录页面 用户管理页面 客房信息查询 酒店详细信息 后台…

APP广告变现怎么实现的,背后逻辑是什么?

广告变现的实现主要基于以下几个关键步骤和逻辑&#xff1a; 用户获取与留存&#xff1a;首先&#xff0c;APP需要吸引足够的用户并确保他们的留存率。只有拥有庞大且活跃的用户基础&#xff0c;APP才能吸引广告商投放广告。因此&#xff0c;开发者需要通过优化APP质量、提升用…

数字人实训室解决方案

前言 近年来&#xff0c;政策层面的积极推动为数字人产业铺设了坚实的基石。2021年&#xff0c;“十四五”规划将虚拟数字技术纳入其中&#xff0c;强调技术创新引领行业应用的革新&#xff0c;加速数字人在各领域的实际应用。紧接着的《“十四五”数字经济发展规划》进一步明确…

Nodejs 第七十三章(网关层)

什么是网关层(getway)&#xff1f; 技术选型fastify 速度快适合网关层 fastify教程上一章有讲 网关层是位于客户端和后端服务之间的中间层&#xff0c;用于处理和转发请求。它充当了请求的入口点&#xff0c;并负责将请求路由到适当的后端服务&#xff0c;并将后端服务的响应…

一个基于HOOK机制的微信机器人

一个基于✨HOOK机制的微信机器人&#xff0c;支持&#x1f331;安全新闻定时推送【FreeBuf&#xff0c;先知&#xff0c;安全客&#xff0c;奇安信攻防社区】&#xff0c;&#x1f46f;Kfc文案&#xff0c;⚡备案查询&#xff0c;⚡手机号归属地查询&#xff0c;⚡WHOIS信息查询…

有哪些地图采集软件可以采集商家数据导出功能?

1.国内商家采集 寅甲地图数据采集软件 寅甲地图数据采集软件一款多关键词多城市同时采集百度地图、360地图、高德地图、搜狗地图、腾讯地图、图吧地图、天地图商家、公司、店铺的手机、座机、地址、坐标等数据信息的软件。 2.国外商家采集 寅甲谷歌地图数据采集软件 专为做…

叶面积指数(LAI)数据、NPP数据、GPP数据、植被覆盖度数据获取

引言 多种卫星遥感数据反演叶面积指数&#xff08;LAI&#xff09;产品是地理遥感生态网推出的生态环境类数据产品之一。产品包括2000-2009年逐8天数据&#xff0c;值域是-100-689之间&#xff0c;数据类型为32bit整型。该产品经过遥感数据获取、计算归一化植被指数、解译植被类…

完成商品SPU管理页面

文章目录 1.引入前端界面1.将前端界面放到commodity下2.创建菜单3.进入前端项目&#xff0c;使用npm添加依赖1.根目录下输入2.报错 chromedriver2.27.2的问题3.点击链接下载压缩包&#xff0c;然后使用下面的命令安装4.再次安装 pubsub-js 成功5.在main.js中引入这个组件 4.修改…

【超详细】固态硬盘新盘验货检测教程

观前声明&#xff1a; 本文使用的固态硬盘为作者自费购买&#xff0c;同时也带有作者一定的主观意见&#xff0c;无任何软件和硬件的推广。 作者本人也正处于学习阶段&#xff0c;本文若有错误或有待改进的地方&#xff0c;欢迎评论区友善讨论~ 一、产品外包装信息检查 PS&…