基于昇腾310的智能打卡系统(课程大作业)
本次实验通过昇腾310实验板,结合摄像头、按键与OLED屏幕,制作一款基于Yolov3的智能打卡系统。摄像头先进行拍摄与采集数据,将拍到的数据送入Yolov3模型中进行人像识别,当且仅当识别到一个人像时,才视为识别成功。接着用户开始输入密码,即按照一定的次序按下板子上的按键,假若密码错误,则在OLED屏幕上显示错误,输入正确后,则在OLED屏幕上显示当前室内的温度和湿度,并记录当前用户的打卡名次,也显示出来。在摄像头识别出人像后,还会将人像从原始图片中截取出来并保存。受到不同用户权限与环境变量不同的影响,分别在HwHiAiUser用户与root用户下同时进行不同的程序,在两个程序之间通过信号量机制进行交替的阻塞与运行。
- 实验设计思路:
说明整个实验的设计思路、所采用的模块、芯片及其各模块或芯片的功能划分等。
所采用的模块:
使用了摄像头模块、按键模块、Sht20温湿度传感器模块、OLED屏幕模块。
设计思路:
根据所选择的模块,将设计思路分为了一下5个部分:基于Yolov3的人像检测、按键密码的设计、OLED屏幕、Sht20与IIC通信、进程间信号量机制,详细说明如下。
- 基于Yolov3的人像检测:
在代码中,首先需要将caffe框架的模型和权重文件转化为昇腾平台下适配的om模型,其次输入指令开启Web服务器;利用opencv打开板子所连接的摄像头,并获取摄像头的每一帧图像数据,将图像送入模型进行识别。在object_detect.cpp文件中接着进行修改,由于考勤打卡系统一个时间内只能接受一个用户的考勤打卡请求,因此在摄像头进行人像识别的时候,当且仅当画面中识别到1个人的情况下,才视为识别成功。为了便于人工的查看,系统还会获取Yolov3识别框的信息,根据该信息从原始图像中将人像截取出来,并保存。人像数量的判断与人像截取代码如图3.1所示。
图3.1 截取人像代码
- 按键密码的设计:
在代码上,需要修改task.c文件,重写按键的绑定函数与回调函数。由代码可知,按钮总共有7种触发方式,分别是PRESS_DOWN(按下触发),PRESS_UP(弹起触发事件),PRESS_REPEAT(按两下触发事件),SINGLE_CLICK(单击按键事件),DOUBLE_CLICK(双击按键事件),LONG_PRESS_START(达到长按时间阈值时触发一次),LONG_PRESS_HOLD(长按期间一直触发),这里选择PRESS_UP为检测的状态,同时将CallBackS2_PRESS_UP作为回调函数,即检测到按下抬起这一状态后,就调用这个函数。绑定按键函数如图3.2所示。在这个函数中,通过创建线程的方式进行运行,密码判断结束后即停止这个线程。按键2代表“2”,按键3代表“3”,密码长度为6位,按下6次按键后即对密码进行判断,假若密码错误,则要求用户重新输入,并在OLED上显示“Wrong Password”,直至用户输入正确的密码为止。
注意,密码输入正确后,会退出判断密码的函数,此时需要注意将先前绑定的按键进行释放,否则会导致下次运行到这个代码时,按下一个按键会响应两次回调函数。
图3.2 按键绑定函数
- OLED屏幕:
OLED屏幕采用IIC的通信形式实现通信,首先需要初始化OLED屏幕,并设置OLED屏幕的显示方式(正色显示、反色显示)。使用ShowString函数进行显示,在该函数中需要指定显示字符的x与y坐标信息,以及需要显示的字符信息。由于Sht20获取的温湿度信息为int类型,因此需要进行转化,利用sprinf函数将int类型的变量转化为char类型。
- Sht20与IIC通信:
使用Sht20温湿度传感器,首先需要对该模块进行初始化,由于要跟OLED屏幕结合使用,因此需要将两者融合在一个函数之中。
该模块需要用到Sht20_Test()与Oled_Test()函数,并对其进行合并。由Oled_Test()函数可知,我们所需要修改的就是,ShowString中的字符串,只需需要使用Sht20_Test()中的Sht20GetData(buff),将温湿度存在buff数组,转换成char类型即可。
但在代码编写过程中,反复遇到段错误报错,这里总结一下报错原因,最后编的代码如图3所示。首先,不仅需要对Sht20进行初始化,还需要对Oled进行初始化,并且初始化函数定义在方法的最前面;其次,由于Sht20获得的buff数组属于float类型,小数点后面的长度过长,难以用char类型数据进行很好的长度约束,因此这里先将float类型的buff数组转化成int类型;接着,用sprintf函数,将int类型的数组转化为char类型,最后利用showstring函数将其显示出来。部分代码如图3.3所示。
图3.3 Sht20部分代码
5、进程间信号量机制:
由于摄像头模块需要调用摄像头与Yolov3模型,而且受到不同用户具有不同的环境变量的因素,因此摄像头模块必须在HwHiAiUser用户下进行运行,而其他模块(如按键模块与Oled模块)需要调用到底层的模块,因此需要执行su root切换到root用户下,因此想要一次性执行两个代码,就需要开启两个终端,一个在HwHiAiUser用户下用于执行摄像头模块,一个在root用户下用于执行按键等其他模块,但两个进程需要按照特定的顺序执行,如何让两个代码之间进行通信就成了需要解决的问题。这里采用了信号量机制,利用一个tmp文件,作为两个程序之间的通信区域。当摄像头识别到一个人像后,就往tmp文件中写入“1”,并阻塞自己,让自己一直处于读取文件内容的状态。其次密码按键模块首先会将自己阻塞,同样令自己处于一直读取文件内容的状态,当从文件中读取了“1”,则立刻进入运行状态,直至用户完成了所有的操作后,再在tmp文件中写入“0”。此时,读到了摄像头模块读到了“0”,则重新开始运行。按照此顺序一直循环运行。部分代码如图3.4所示。
图3.4 信号量部分代码
- 实验流程图:
- 执行结果:
首先往tmp文件,手动清空并写入“0”,再在终端运行代码,如图4.1所示,右边为摄像头模块代码,左边为其他模块代码。从tmp文件中读取到“0”后,摄像头开始工作,捕获图像数据,并传入Yolov3模型进行识别,识别结果在网站上可以观察到,当识别到两个及两个以上的人像数据时,则人像识别失败,重新捕获图像并重新识别,如图4.2所示。当且仅当识别到一个人像的时候,则识别成功,如图4.3所示。摄像头模块程序清空tmp文件,并往tmp文件中写入“1”,由于没有读到“0”,因此摄像头模块程序阻塞。
图4.1 开始运行代码
图4.2 识别到两个人像
图4.3 识别到一个人像
其他模块代码同样需要打开并读取tmp文件,由于需要读到“1”,因此一开始该模块代码会阻塞,当代码摄像头模块程序写入了“1”后,即可解除阻塞状态,进行密码的输入。这里按照一定的顺序按下按键,如图4.4所示,输入了错误的密码,则在OLED上显示错误信息,如图4.5所示。输入正确的密码后,显示当前用户的打卡名次,利用IIC操作获取温湿度信息,同样在OLED上显示出来。完成后,清空tmp文件,在tmp文件中写入“0”,使得当前模块程序进入阻塞状态。而摄像头读到了“0”,因此重新工作,重复上述运行的过程。
图4.4 输入错误密码
图4.5 OLED显示错误信息
图4.6 OLED显示正确的信息
- 总结与展望
本次实验进行了关于智能打卡系统的设计, 结合摄像头、OLED屏幕、按键、Sht20等等模块,通过IIC通信与终端之间的信号量机制实现了用户的考勤打卡。当然在本次实验中,也有一些不足,受限于模型与语言,因此这里只用了Yolov3进行单纯的人像识别,不能对特定的人脸进行识别。因此希望可以能够在优化的时候加入人脸识别,提高系统的安全性。此外,本来在系统设想中,还希望加入蓝牙模块,以及利用WiFi进行联网,获取当地的天气信息,但也受限于ESP32模块没有烧录成功,以及疫情原因无法去实验室重新烧录,因此最终也没有实现。
本次实验,我接触到了昇腾310板子,改板搭载了两个达芬奇Ai Core,采用华为自研的高效灵活CISC指令集和自研达芬奇架构。与其他课程不同,经过了本次课程,我接触了位于时代前沿的科技,并进行了简单的应用,通过编写代码,进行Yolov3模型的推理,我也充分利用到了昇腾310上的Ai Core,让我对华为昇腾310有了深刻的印象。在实验中,我使用到了摄像头、按键、OLED、Yolov3模型等等部分,不仅仅让我对嵌入式这一门学科方向有了亲身的体会与清晰的定位,在计算机的底层解决问题,实现部件与部件之间的通信,加深了我对计算机底层运行与通信的理解,也让我对嵌入式产生了浓厚的兴趣。在以后的学习道路上,我希望能够继续接触到嵌入式的相关内容,希望能够将人工智能算法应用到嵌入式设备上,实现一系列的功能。
- 点赞
- 收藏
- 关注作者
评论(0)