单片机开发---基于ESP32-CAM的人脸识别应用
背景
学习了一下OpenCV,熟悉了一点基础概念,就寻找了一下单片机上能否支持人脸识别,用来做一些小玩意。
结果还真发现了一个模块叫ESP32-CAM。ESP32-CAM算得上是一款最便宜的支持人脸识别的单片机开发板了,性能算是单片机里相当不错的了,虽然也只是勉强支持了人脸识别。但是它的优势也是巨大的,就是价格,太便宜了!!
并且在B站上看到了这位大佬的作品:
基于esp32cam人脸识别开锁完整教程&独家教程
于是也来学一下这个模块的使用。顺便问一下
几十块钱的人脸识别门锁,你敢不敢用。
不过可以拿来给孩子做个玩具。
软硬件准备
- 硬件方面
淘宝了一个带底座的ESP32-CAM模块,这个底座主要就是解决了供电和烧录,直接插上就能连接电脑了。
- 软件方面
参照使用手册,搭建了arduino的开发环境,安装了最新的ESP32支持包,可以跑一下官方的范例,能够进行人脸识别。买开发板都会赠送这个教程,这里就不细说了。
不过官方的范例,代码有些混乱,还是大佬开源的这版代码看着逻辑比较清晰。
详解人脸识别门锁
视频中的大佬将他的代码都奉献出来了,在此表达感谢,大家可以去支持一下。
代码可以下载下来,自己进行一下理解。
不过大佬的代码在我这里运行的时候,会报错,fr_flash的错误,这个我还没找到问题原因,可能就是无法将识别出来的人脸数据,存储起来,导致,每次重启都需要重新录入人脸。
先讲一下人脸识别的关键点。
首先是获取视频,使用的是下面的接口
fb = esp_camera_fb_get();
然后将视频转化为RGB888,使用的是下面的接口
fmt2rgb888(fb->buf, fb->len, fb->format, out_res.image);
人脸的操作,分为了检测(查看有没有人脸),录入(将人脸的特征值存储下来),和识别(识别摄像头拍摄到的人脸是不是在库中)。三种操作都需要进行人脸检测。使用到的接口是
out_res.net_boxes = face_detect(image_matrix, &mtmn_config);
然后将人脸对齐
align_face(out_res.net_boxes, image_matrix, aligned_face)
再提取特征值
out_res.face_id = get_face_id(aligned_face);
注意,这个face_id就是最最核心的数据,是你人脸的特征值。有了这个数据,你就可以进行人脸的判断了。
如果是录入,就需要将这个数据进行存储;
如果是识别,就需要将这个数据与已经存储的特征进行对比,符合就说明拍摄到了对的人。
特征对比的核心函数如下
face_id_node *f = recognize_face_with_name(&st_face_list, out_res.face_id);
其中st_face_list就是一个链表,里面的数据就是已经存储好的face_id。
整个代码思路理清之后,就容易修改了。我们来看一下这个face_id的数据是什么结构。
typedef struct tag_face_id_node
{struct tag_face_id_node *next; /*!< next face id node */char id_name[ENROLL_NAME_LEN]; /*!< name corresponding to the face id */dl_matrix3d_t *id_vec; /*!< face id */
} face_id_node;typedef struct
{int w; /*!< Width */int h; /*!< Height */int c; /*!< Channel */int n; /*!< Number of filter, input and output must be 1 */int stride; /*!< Step between lines */fptp_t *item; /*!< Data */
} dl_matrix3d_t;
可以看出来这个特征值,就是下面那个结构。
我尝试着打印了一个组数据,发现item为一个512长度的float数组。这就是你人脸的特征,应该也算是你的生物指纹之一吧,这么轻松就能获取到了。
flash问题解决
那么就来解决一下flash中没有成功存储face_id的问题吧,
启动的时候,系统调用了这个函数
read_face_id_from_flash_with_name(&st_face_list);
应该就是报错的原因,那么我们不用这个flash存储了,改用数组或者文件直接存储即可。
正好有内存卡可以使用。参考的代码就是SD_MMC这个范例代码。
大概原理就是将用户数据建成目录,每个用户录入一组特征值,即faceID,录入的时候,分别存储到对应目录中。
开机启动的时候,通过读取每个目录,形成核心对比数据,放在st_face_list变量中。
两个核心函数,保存ID
void SD_save_face_id(char* name,int number,dl_matrix3d_t *face_id)
{int num=0;char filename[32]={0};unsigned char* data=NULL;num=(face_id->w)*(face_id->h)*(face_id->c)*(face_id->n);sprintf(filename,"/%s",name);SD_createDir(SD_MMC,filename);sprintf(filename,"/%s/1.txt",name);data=(unsigned char*)face_id->item;SD_writeFile(SD_MMC, filename, data,num*4);
}
读出ID
void SD_read_all_face_id(fs::FS &fs)
{st_face_list.count=0;st_face_list.head=NULL;st_face_list.tail=NULL;st_face_list.confirm_times=5;face_id_node* faceidnode_now=NULL;File root = fs.open("/");if(!root){Serial.println("Failed to open directory");return;}if(!root.isDirectory()){Serial.println("Not a directory");return;}File file = root.openNextFile();while(file){if(file.isDirectory()){face_id_node* faceidnode=NULL;char fullname[64]={0};Serial.printf("find user:[%s]\n",file.name());sprintf(fullname,"%s/1.txt",file.name());File tryopen = fs.open(fullname);if(!tryopen){Serial.printf("user has no face id[%s]\n",fullname);file = root.openNextFile();continue;}else{faceidnode = (face_id_node*)dl_lib_calloc(1, sizeof(face_id_node), 0);if(faceidnode){dl_matrix3d_t* id_vec;strcpy(faceidnode->id_name,file.name()+1);id_vec= (dl_matrix3d_t*)dl_lib_calloc(1, sizeof(dl_matrix3d_t), 0);if(id_vec){float* face=NULL;faceidnode->id_vec=id_vec;faceidnode->next=NULL;id_vec->w=1;id_vec->h=1;id_vec->c=512;id_vec->n=1;id_vec->stride=512;face= (float*)dl_lib_calloc(512, sizeof(float), 0);tryopen.read((unsigned char*)face,512*4);id_vec->item=face;if(st_face_list.head==NULL){st_face_list.head=faceidnode;st_face_list.tail=faceidnode;faceidnode_now = faceidnode;}else{st_face_list.tail=faceidnode;faceidnode_now->next=faceidnode;faceidnode_now=faceidnode;}st_face_list.count++;}}}} file = root.openNextFile();}
}
其他操作函数最终见下载,都放上来就太多了。
来吧 展示
烧录好之后,访问web。
可以先录入人脸
输入名字,点击ADD USER,我这里用一个图片代替一下。
然后点击ACCESS CONTROL,进行人脸识别
识别成功,会提示DOOR OPEN FOR test。
重启之后,信息不会再丢失。
有人问,这个美女是谁啊,那有点不好意思了,这是个男的。
卡顿问题
这个模块的信号可能不太好,距离路由器远了之后,就会很卡,很奇怪的是,我家用了一个路由器进行了信号的增强覆盖,这个模块接到扩展的路由器上,一样也会变的卡顿。
所以我就单独用了一个路由器,将摄像头模块和电脑组成了一个局域网,而且得把模块放在路由器附近,这样就不再卡顿了。
后续考虑是不是改一下用外置天线,看看是不是天线的问题导致的。
用灯代替门锁
这个模块RST按钮旁边有一个板载红色LED。该LED内部连接到GPIO 33。您可以使用此LED指示正在发生的事情。例如,如果连接了Wi-Fi,则LED为红色,反之亦然。
该LED具有反向逻辑,因此您发送了一个 LOW 信号打开它 HIGH 信号将其关闭。
所以可能模拟红灯亮起,表示开锁,同理这个GPIO可以让你用来触发一些别的操作而不仅限于开锁,开灯,开水龙头,想开啥开啥。
代码下载
大佬的代码,还请去B站观看一下,然后在评论区即可看到下载链接。
我的代码下载
改这个存储用了一天的时间,所以还是用了点小心机。
结束语
你们知道人生的意义是什么吗?分享给你们一张图吧
其实我觉得人生有意义,我们的意义,存在于我们对别人的意义。
单片机开发---基于ESP32-CAM的人脸识别应用相关推荐
- 基于ESP32 CAM的人脸识别考勤系统
概述:使用 ESP32 CAM 的人脸识别考勤系统 本教程介绍了使用ESP32 CAM 模组的人脸识别考勤系统.我们将为此应用程序使用OpenCV和Visual Studio .OpenCV 是一个开 ...
- 开发基于深度学习的人脸识别【考勤/签到】系统
开发基于深度学习的人脸识别[考勤/签到]系统 人脸识别介绍 平台环境需求 技术点 系统流程 细节设计 人脸检测 人脸关键点定位 人脸特征提取 模型的训练 模型的部署 MySQL数据库的使用 MFC工程 ...
- 手把手教你开发基于深度学习的人脸识别【考勤/签到】系统
人脸识别介绍 平台环境需求 技术点 系统流程 细节设计 人脸检测 人脸关键点定位 人脸特征提取 模型的训练 模型的部署 MySQL数据库的使用 MFC工程的搭建 软件使用 人脸识别介绍 人脸识别技术是 ...
- android人脸识别demo_C#开发实录:基于免费SDK实现人脸识别应用开发
随着人脸识别技术应用范围不断扩展,如何在Windows C#上基于免费SDK实现人脸识别应用开发,正成为开发者们关心的话题之一. 对于该需求,我推荐虹软视觉开放平台的ArcFace 3.0,免费.离线 ...
- 【优秀课设】基于OpenCV-Python的树莓派人脸识别及89C52单片机控制系统设计(指定照片进行识别、遍历目录下所有照片依次识别)
基于OpenCV-Python的树莓派人脸识别及89C52单片机控制系统设计 (指定照片进行识别) 参照之前的文章所改进 增加视频随时标注功能 https://blog.csdn.net/weixin ...
- 【优秀课设】基于OpenCV的Python人脸识别、检测、框选(遍历目录下所有照片依次识别 视频随时标注)
基于OpenCV的Python人脸识别.检测.框选 (遍历目录下所有照片依次识别 视频随时标注) 移步: https://blog.csdn.net/weixin_53403301/article/d ...
- 基于全局信息的人脸识别总结
一. 课题名称 基于全局信息的人脸识别算法研究 二. 课题的提出 在当今社会中,身份确认具有十分重要的价值.随着网络技术的发展,信息安全也显示出了前所未有的重要 ...
- 《繁凡的论文精读》(一)CVPR 2019 基于决策的高效人脸识别黑盒对抗攻击(清华朱军)
点我一文弄懂深度学习所有基础和各大主流研究方向! <繁凡的深度学习笔记>,包含深度学习基础和 TensorFlow2.0,PyTorch 详解,以及 CNN,RNN,GNN,AE,GAN, ...
- 基于PYQT编写一个人脸识别软件
转载请注明出处:http://blog.csdn.net/hongbin_xu 或 http://hongbin96.com/ 文章链接:http://blog.csdn.net/hongbin_xu ...
- 身份验证错误错误指定的句柄无效_基于 Web 端的人脸识别身份验证「实践」
作者:沫沫 政采云前端团队 转发链接:https://mp.weixin.qq.com/s/fRDpXixnLIy9c0Uh2tMezQ 前言 近些年来,随着生物识别技术的逐渐成熟,基于深度学习的人脸 ...
最新文章
- mysql-5.7.24-winx64忘记密码该咋解决
- PyQt5教程——组件 Ⅱ(八)
- 提高使用比特币的匿名性
- 归算法及经典递归例子代码实现
- 矩阵分析与多元统计11 广义vec算子与devec算子
- Android有返回值的Activity
- Android之webview长按超链接类型获取链接文字及url、长按图片链接类型分别获取图片和链接的url
- kmp学英语必须设置
- 中国移动携手华为完成5G话音的全部功能测试
- vscode ---- 插件
- validate中remote的用法
- Fluter拓展 图标库
- python Udp与Tcp
- 雷电4模拟器安装xposed框架(2022年)
- Excel文本取首字母(包括繁体)VBA开发工具
- 明日复明日,明日何其多;我生待明日,万事成蹉跎
- 软件开发、软件设计培训笔记
- Spring Batch(三) 详细介绍Job Launcher、ItemReader、ItemProcessor、ItemWriter各个实现类和用途
- js对内容进行编码(富文本编辑器使用居多)
- 同样是IT行业,测试和开发薪资真有这么大差别?