基于RV1126开发板实现驾驶员行为检测方案
1. 计划简介
驾驶员行动检测:经过图象辨认出那几种行动:挨德律风、吸烟、疲惫驾驶。
2. 疾速上脚
2.1 开辟情况预备
假如您初度浏览此文档,请浏览《进门指北/开辟情况预备/Easy-Eai编译情况预备取更新》,并依照其相干的操纵,停止编译情况的摆设。
正在PC端Ubuntu零碎中履行run剧本,进进EASY-EAI编译情况,详细以下所示。
cd ~/develop_environment ./run.sh

2.2 源码下载和真例编译
正在EASY-EAI编译情况下创立寄存源码堆栈的治理目次:
cd /opt mkdir EASY-EAI-Toolkit cd EASY-EAI-Toolkit
经过git东西,正在治理目次内克隆近程堆栈
git clone https://github.com/EASY-EAI/EASY-EAI-Toolkit-C-Solution.git
注:
* 此处能够会果收集缘由形成卡顿,请耐烦等候。
* 假如真实要正在gitHub网页高低载,也要把全部堆栈下载上去,不克不及独自下载本真例对应的目次。
进进到对应的例程目次履行编译操纵,详细号令以下所示:
cd EASY-EAI-Toolkit-C-Solution/solu-dms/ ./build.sh
注:
* 因为依靠库摆设正在板卡上,因而穿插编译进程中必需坚持adb衔接。
注:
* 若build.sh剧本没有带任何参数,则仅会拷贝solution编译出去的可履行文件。
* 若build.sh剧本带有cpres参数,则会把Release/目次下的一切资本皆拷贝到开辟板上。
* 若build.sh剧本带有clear参数,则会把build/目次战Release/目次删除。
2.3 模子获得
【百度网盘】
链接:https://pan.百度.com/s/1mrhVHxHWJ8cY9Fl9k5KtYg
提与码:0k7j
本计划用到四个模子:face_detect.model、face_landmark98.model、phonecall_detect.model、smoke_detect.model
间接把模子下载到当地Windows主机,复造
进进PC端Ubuntu创立寄存model目次:
cd /opt mkdir model

然后把模子从当地Windows主机粘揭到PC端Ubuntu中:
2.4 计划摆设
运用下圆号令再次回到开辟真例目次
cd /opt/EASY-EAI-Toolkit-C-Solution/solu-dms/
然后,将EASY-EAI编译情况的编译后果摆设到板卡中(有两种办法)。
办法一:经过履行以下号令脚动摆设【引荐】
cp Release/* /mnt/userdata/Solu
办法两:正在编译时减上编译参数主动摆设
./build.sh cpres
最初,将预备好的模子摆设到板卡中(留意:模子要放到编译后果的统一目次中),履行号令以下所示。
cp /opt/model/*.model /mnt/userdata/Solu
2.5 示例计划运转
经过按键Ctrl+Shift+T创立一个新窗心,履行adb shell号令,进进板卡运转情况。
adb shell
进进板卡后,定位到例程摆设的地位,以下所示:
cd /userdata/Solu
运转例程号令以下所示:
./solu-dms
2.6 运转结果
运转挨印:
root@EASY-EAI-NANO:/userdata/Solu# ./solu-dms media get entity by name: rkcif-lvds-subdev is null media get entity by name: rkcif-lite-lvds-subdev is null media get entity by name: rkisp-mpfbc-subdev is null media get entity by name: rkisp_dmapath is null media get entity by name: rkisp-mpfbc-subdev is null media get entity by name: rkisp_dmapath is null media get entity by name: rockchip-mipi-dphy-rx is null [15:47:08.490666][CAMHW]:XCAM ERROR CamHwIsp20.cpp:928: No free isp&ispp needed by fake camera! Rga built version:1.04 94a2c08+2023-04-12 10:23:53 Had init the rga dev ctx = 0x9197d0 Rga built version:1.04 94a2c08+2023-04-12 10:23:53 ##RKMEDIA Log level: 2 …… librknn_runtime version 1.7.3 (2e55827 build: 2022-08-25 10:45:32 base: 1131) librknn_runtime version 1.7.3 (2e55827 build: 2022-08-25 10:45:32 base: 1131) librknn_runtime version 1.7.3 (2e55827 build: 2022-08-25 10:45:32 base: 1131) librknn_runtime version 1.7.3 (2e55827 build: 2022-08-25 10:45:32 base: 1131) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> driver state : >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> driver state : >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> driver state : [Is tired] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> driver state : [Is tired] [Smoking] [Phone Calling] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> driver state :
假如从摄像头绘里中检测到驾驶员有非常行动,背景会挨印出被检测到的非常行动标签:
而且会屏幕右边显现对应的形态。
2.7 开机启动
起首进进板卡情况,履行以下号令,正在板卡上创立一个给本例程运用的使用目次:myapp
cd /userdata/apps/ mkdir myapp

然后回到开辟情况中,经过运用“2.4计划摆设”相似的操纵办法,把本例程所需求的全数文件,包括:编译后果,设置装备摆设文件,模子等。摆设到方才新建的myapp目次中。
最初正在板卡上创立一个run.sh剧本去管控用户一切需求的使用便可,《进门指北/使用顺序开机自启动》会具体描绘run.sh剧本该若何编写。
3. 代码剖析
计划主逻辑代码位于:EASY-EAI-Toolkit-C-Solution/solu-dms/src/main.cpp。代码完成次要经过挪用我司的easyeai-api库疾速完成驾驶员行动检测功用,代码主体分为主线程战算法剖析子线程。
3.1 组件库构成
要完成平安帽检测功用,需求运用到easyeai-api库的以下组件,以下所示。
模组疑息以下所示。
组件 | 头文件和库途径 | 描绘 |
零碎操纵组件 | easyeai-api/common_api/system_opt | 供给线程操纵函数 |
摄像头组件 | easyeai-api/peripheral_api/camera | 供给摄像头操纵函数 |
显现屏组件 | easyeai-api/peripheral_api/display | 供给显现屏操纵函数 |
人脸检测组件 | easyeai-api/algorithm_api/face_detect | 供给人脸检测操纵函数 |
人脸98要害面组件 | easyeai-api/algorithm_api/face_landmark98 | 供给人脸98要害面操纵函数 |
抽烟检测组件 | easyeai-api/algorithm_api/smoke_detect | 供给抽烟检测操纵函数 |
挨德律风检测组件 | easyeai-api/algorithm_api/phonecall_detect | 供给挨德律风检测操纵函数 |
那些组件经过CMakeLists.txt编译进工程,详细请看后绝章节。
3.2 逻辑框图
项目标全体逻辑框图以下所示。
3.3 主线程
主线程处置的营业有:
初初化中设;
创立算法剖析子线程;
抓图收收给到子线程;
抓图、显现;
本处附上次要的逻辑功用代码,其他辅佐的、校验型的代码先疏忽。
组件初初化操纵以下,本处挪用RGB摄像头。
// 1.翻开摄像头 ret = rgbcamera_init(CAMERA_WIDTH, CAMERA_HEIGHT, 90); pbuf = NULL; pbuf = (char *)malloc(IMAGE_SIZE);
创立线程互斥锁和线程,以下所示。
// 2.创立辨认线程,和图象互斥锁 pthread_mutex_init(&img_lock, NULL); pResult = (Result_t *)malloc(sizeof(Result_t)); memset(pResult, 0, sizeof(Result_t)); if(0 != CreateNormalThread(detect_thread_entry, pResult, &mTid)){ free(pResult); }
初初化显现屏,以下所示。
// 3.显现初初化 #define SCREEN_WIDTH 720 #define SCREEN_HEIGHT 1280 screen.screen_width = SCREEN_WIDTH; screen.screen_height = SCREEN_HEIGHT; screen.wins[0].rotation = 270; screen.wins[0].in_fmt = IMAGE_TYPE_BGR888; screen.wins[0].enable = 1; screen.wins[0].in_w = 640; screen.wins[0].in_h = 720; screen.wins[0].HorStride = screen.wins[0].in_w; screen.wins[0].VirStride = screen.wins[0].in_h; screen.wins[0].crop_x = 0; screen.wins[0].crop_y = 0; screen.wins[0].crop_w = 640; screen.wins[0].crop_h = 720; screen.wins[0].win_x = 0; screen.wins[0].win_y = 0; screen.wins[0].win_h = 640; screen.wins[0].win_w = 720; screen.wins[1].rotation = 270; screen.wins[1].in_fmt = IMAGE_TYPE_BGR888; screen.wins[1].enable = 1; screen.wins[1].in_w = CAMERA_WIDTH; screen.wins[1].in_h = CAMERA_HEIGHT; screen.wins[1].HorStride = CAMERA_WIDTH; screen.wins[1].VirStride = CAMERA_HEIGHT; screen.wins[1].crop_x = 0; screen.wins[1].crop_y = 0; screen.wins[1].crop_w = 640; screen.wins[1].crop_h = 720; screen.wins[1].win_x = 0; screen.wins[1].win_y = 640; screen.wins[1].win_h = 640; screen.wins[1].win_w = 720; ret = disp_init_pro(&screen); if (ret) { printf("error: %s, %dn", __func__, __LINE__); goto exit1; }
抓与图象,挪用clone操纵。
// 4.(与流 + 显现)轮回 pthread_mutex_lock(&img_lock); ret = rgbcamera_getframe(pbuf); algorithm_image = Mat(CAMERA_HEIGHT, CAMERA_WIDTH, CV_8UC3, pbuf); image = algorithm_image.clone(); pthread_mutex_unlock(&img_lock);
挪用显现图象接心,一边显现镜头绘里,另外一边经过Result将剖析的后果显现对应的形态。
// 依据形态揭提醒图 if(driverState != Result.drvState){ driverState = Result.drvState; if(0 == driverState){ tipsImage = cv::imread("normal.jpg",1); }else if(driverState & (0x01<
3.4 算法剖析子线程
算法剖析子线程,次要完成以下操纵:
延时监测能否图象缓冲区能否为空;
没有为空时,证实主函数已收收图象数据过去,线程履行图象获得操纵;
挪用抽烟检测剖析函数;
挪用挨德律风检测剖析函数;
挪用人脸检测剖析函数,和人脸98要害面剖析函数
记载模子输入的数据,剖析数据并输入算法后果,并用于后绝显现绘里分解操纵;
延时监测能否有图象,操纵以下所示。
if(algorithm_image.empty()) { usleep(5); continue; }
获得图象操纵以下所示。
pthread_mutex_lock(&img_lock); image = algorithm_image.clone(); pthread_mutex_unlock(&img_lock);
挪用抽烟检测函数,算法失掉的目的后果记载于pResult内,以下所示。
/* 1.吸烟检测 */ ret = smoke_detect_run(smokeCtx, image, &pResult->smoke_result);
挪用挨德律风检测函数,算法失掉的目的后果记载于pResult内,以下所示。
/* 2.挨德律风检测 */ ret = phonecall_detect_run(pcCtx, image, &pResult->phonecall_result);
挪用人脸检测剖析函数,和人脸98要害面剖析函数。失掉后果后剖析能否有闭眼,挨哈短等举措。
// 人脸检测 ret = face_detect_run(faceCtx, image, pResult->face_result); // 把人脸裁出,并按256x256像素停止图象缩放 cv::Mat roi_img, reize_img; roi_img = image(cv::Rect(x, y, max,max)); roi_img = roi_img.clone(); resize(roi_img, reize_img, Size(256,256), 0, 0, INTER_AREA); pResult->ratio = (float)max/256; // 把256x256的人脸图象收进98要害面函数找出98个要害面 ret = face_landmark98_run(landmarkCtx, &reize_img, &keyPoints); // 把98个要害面收进【闭眼】,【挨哈短】判别函数 if(eyesClosing(keyPoints)||yawning(keyPoints)){ tired_count++; }else{ tired_count = 0; } // 【闭眼】或【挨哈短】举措延续保持3次以上,则判别为【疲惫】形态 if(3 <= tired_count){ pResult- >drvState |= (0x01< drvState &=~(0x01< ().swap(keyPoints);
4. 开辟指北
4.1 示例文件&目次构造
Solution git堆栈会跟着产物迭代更新,不时新删处理计划代码,以后截图只做参考。
4.1.1 Solution git堆栈目次引见。
Solution工程组成以下所示,由功用组件easyeai-api战各个处理计划组成。
单个“solu-”扫尾的目次即为一个处理计划案例,代码内挪用“EASY EAI-API”去知足某一实践使用场景的需供。
功用组件的描绘以下所示,easyeai-api是颠末下度启拆的易用性组件接心,便于用户间接挪用板卡资本。
功用 | 组件目次 | 组件子目次 | 描绘 |
功用组件 | easyeai-api | algorithm_api | 算法组件 |
common_api | 通用组件 | ||
media_api | 多媒体组件 | ||
netProtocol_api | 收集和谈组件 | ||
peripheral_api | 中设硬件组件 |
4.1.2 处理计划最根本的目次组成。
每一个处理计划便是一个自力的项目,项目内包括局部以下所示,项目运用cmake构建主动编译摆设。
详细引见以下所示。
构成局部 | 描绘 |
build.sh | 编译剧本,用于治理死成可履行文件后的摆设预备任务,用户可自界说shell号令 |
CMakeLists.txt | 工程治理文件,用于构造全部工程构造,指点cmake死成Makefile |
include | 用于寄存第三圆使用库、头文件目次等 |
src | 用于寄存完成本计划需供的源代码 |
4.1.3 处理计划可拓展的目次组成。
可拓展的目次是指:开辟进程中添加某些功用模块,功用代码。添加形式分为两种:
添加已编译的第三圆库,正在include、libs目次内增加头文件战库文件;
添加用户自界说的功用模块,引荐正在src目次内添加;
详细状况以下所示,第三圆模块相干的文件由include/3rd_model/xxx.h、libs/3rd_model/xxx.a。自界说的功用模块为src/mySrcCode、src/mySrcCode2。
4.2 CMakeLists.txt文件剖析
4.2.1 编译情况设置装备摆设局部:
第一局部为设置装备摆设局部,设置装备摆设局部以下所示。(获得以后计划目次、设置装备摆设东西链、提与计划称号):
设置装备摆设疑息以下所示。
设置装备摆设项 | 描绘 |
CMake请求版本 | cmake_minimum_required函数指定,请求的最低版本 |
CMAKE_SYSTEM_NAME | cmake的零碎范例,穿插编译必需 |
CMAKE_CROSSCOMPILING | cmake能否启动穿插编译 |
cross.camke | camke_host_system_information获得仄台疑息,发明没有是armv7l便导进以后仄台的穿插编译设置装备摆设。 |
project项目名 | 由project函数指定 |
4.2.2 easyeai-api设置装备摆设局部
第两局部是引进我司的功用组件库(针对以后计划停止:设置装备摆设EASY EAI API头文件目次、库文件目次和设置装备摆设库链接参数):
设置装备摆设疑息以下所示。
设置装备摆设项 | 描绘 |
api_inc | 终究经过target_include_directories函数指定目的包括的头文件途径 |
link_directories | 由link_directories函数指定easyeai-api库地点途径 |
LINK_LIBRARIES | 由LINK_LIBRARIES函数指定easyeai-api库文件 |
4.2.3 第三圆库设置装备摆设局部
第三局部设置装备摆设第三圆的库(针对以后计划停止:设置装备摆设第三圆头文件目次、库文件目次、设置装备摆设第三圆库链接参数和设置装备摆设源码目次):
设置装备摆设疑息以下所示。
设置装备摆设项 | 描绘 |
custom_inc | 自界说变量custom_inc,终究经过target_include_directories函数指定目的包括的头文件途径,正在源码include目次下 |
link_directories | 由link_directories函数指定第三圆库地点途径 |
custom_libs | 自界说变量custom_libs,终究经过target_link_libraries函数指定目的援用的库链接参数 |
aux_source_directory | 自界说变量dir_srcs,用于增加工程代码和自界说的团体代码 |
比方增加团体库的目次构成体例以下所示。
aux_source_directory的修正体例为:
aux_source_directory(./src ./src/mySrcCode ./src/mySrcCode2 dir_srcs)
或
aux_source_directory(./src dir_srcs) aux_source_directory(./src/mySrcCode dir_srcs) aux_source_directory(./src/mySrcCode2 dir_srcs)
4.2.4 本计划设置装备摆设局部
第四局部设置装备摆设项目标编译疑息,内容以下所示:
设置装备摆设项以下所示。
设置装备摆设项 | 描绘 |
add_executable |
编译后果为${CURRENT_FOLDER}指定,即计划目次名; 编译的源文件为${dir_srcs}指定; |
target_include_directories | 指定头文件的名字,由${api_inc}取${custom_inc}指定; |
target_link_libraries | 指定额定的库,比方opencv的库等 |
4.3 build.sh编译剧本:
4.3.1 途径定位局部
第一局部用于提与目次用于编译操纵,内容以下所示:(进进build.sh剧本地点目次,而且提与以后目次相对途径,提与以后目次称号)
4.3.2 肃清编译局部
第两局部肃清操纵,肃清目次为build、Release,内容以下所示:(履行build.sh剧本时,带进了参数“clear”,则浑空编译输入)
4.3.3 编译操纵
第三局部,编译间接挪用cmake,内容以下所示:(从头编译,成摆设目次,并把资本主动摆设进板卡)
考核编纂 黄宇