【EPS32S3学习笔记】ESP32+OPENCV+人脸识别 本地部署

您所在的位置:网站首页 人脸识别能不能视频电话刷脸 【EPS32S3学习笔记】ESP32+OPENCV+人脸识别 本地部署

【EPS32S3学习笔记】ESP32+OPENCV+人脸识别 本地部署

2024-07-12 02:37| 来源: 网络整理| 查看: 265

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用

提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录 系列文章目录前言一、修改.sh文件,将objdetect库链接进来二、增加loadFromMemory接口1.利用winhex将xml文件导出到.c文件2.构建loadFromMemory接口3.参考示例 总结

前言

提示:这里可以添加本文要记录的大概内容:

从https://github.com/joachimBurket/esp32-opencv的TTGO Demo到想要人脸识别(或者其他检测)在opencv上运行,主要需要实现的就是objdetect库的静态编译。下面一步步把我的实现过程分享一下,由于对C++的不熟悉,中间走了一些弯路,感谢ChatGPT,作为工作小助手来说,实在是表现得不错。

ESP32+OPENCV+FaceDetect

提示:以下是本篇文章正文内容,下面案例可供参考 前提环境:ubuntu20.04

一、修改.sh文件,将objdetect库链接进来

在源文件目录下,找到esp32-opencv-master/esp32s3/scripts/文件夹,打开build_opencv_for_esp32s3.sh。(使用esp32目录下得也是可以的,针对得芯片不同)

# list of modules to compile OPENCV_MODULES_LIST=core,imgproc,imgcodecs,objdetect,zlib

修改modules_list,将objectect添加进去。zlib好像本身core已经包含了,可以不添加。 之后运行.sh文件,编译完成之后,印象里会提示flann相关的有一个接口不可用,不可用的原因可能是跟GCC及编译器的缘由,错误类型是一些语法方面的警告,存在风险。这里可以可以直接屏蔽相关语句,把错误跳过去。 之后就可以完成静态库的编译,当然这只是第一步。

二、增加loadFromMemory接口

了解了一下C++和python环境下,opencv实现人脸识别的程序代码。可以参考:https://blog.csdn.net/new9232/article/details/127288336 第一步都是要加载用于检测的CascadeClassifier文件(级联分类器)。对于windows、linux、android这些操作系统来说,这是非常简单的,因为本身都有非常完善的文件系统。而ESP32S3本身是不带文件系统的,当然可以在esp32上运行MicroPython系统,但是怎样将opencv集成到上面,如何在上面运行之前实现的功能(屏幕、触摸、摄像头等),都是一些难题。所以还是在现有的框架下想办法。 也是看了load接口的源码收到一些启发。

bool CascadeClassifierImpl::load(const String& filename) { oldCascade.release(); data = Data(); featureEvaluator.release(); FileStorage fs(filename, FileStorage::READ); if( !fs.isOpened() ) return false; FileNode fs_root = fs.getFirstTopLevelNode(); if( read_(fs_root) ) return true; // probably, it's the cascade in the old format; // let's try to convert it to the new format FileStorage newfs(".yml", FileStorage::WRITE+FileStorage::MEMORY); haar_cvt::convert(fs_root, newfs); std::string newfs_content = newfs.releaseAndGetString(); newfs.open(newfs_content, FileStorage::READ+FileStorage::MEMORY); fs_root = newfs.getFirstTopLevelNode(); if( read_(fs_root) ) return true; return false; }

其中在加载分类器文件之后,代码内部还做了一些处理,在内存中构建了一个.xml文件,并且对加载之后文件进行了重建(怕是一些早期的分类器文件,格式不对)。之后再重新写入到内存中的这个文件,最后从内存中的文件中寻找节点。 于是总体的思路有了,这些xml文件我们可以用现成的,或者以后自己训练完成的,将xml转换为.c格式数据数组,这样就可以加载到程序中,再通过内存构建方式,构建一个存在于内存中的文件,用来给之后的人脸识别使用。 当然过程没有说的那么简单,也是试错了很多。

1.利用winhex将xml文件导出到.c文件

将从原文件中的xml文件用winhex打开,我这里用的是haarcascade_frontalface_alt.xml: 在这里插入图片描述 注:把原来xml文件中的一些注释内容删掉,一个是占内存,另外好像加载的时候容易失败。 选择 编辑》复制所有》C源码 在这里插入图片描述 这样就得到了十六进制的原始数据,在工程中新建一个.c文件,将拷贝的内容复制进去。 另外修改一下变量的定义方式:

const char haarcascade_frontalface_alt[] = {

为什么要这么修改后面就知道了。

2.构建loadFromMemory接口

直接附上代码了:

bool CascadeClassifierImpl::loadFromMemory(const String& fileBuffer) { oldCascade.release(); data = Data(); featureEvaluator.release(); FileStorage newfs(fileBuffer, FileStorage::READ+FileStorage::MEMORY); FileNode fs_root = newfs.getFirstTopLevelNode(); if( read_(fs_root) ) return true; return false; }

功能就是从内存中(String类型的缓冲区),加载一个文件。文件是之前保存在fileBuffer中的。

3.参考示例 static CascadeClassifier faceCascade; const String xmlString(haarcascade_frontalface_alt); bool faceCascadeInit(void) { opencvLogInit(); ESP_LOGW(TAG, "load xml"); if (faceCascade.loadFromMemory(xmlString)){ ESP_LOGW(TAG, "Load OK"); return 1; } else { ESP_LOGW(TAG, "Load Fail"); return 0; } }

这里就明白为什么之前的xml文件要那么定义,是为了方便的构建xmlString变量。 这样就可以完成分类器文件的加载,之后就可以使用这个分类器进行人脸识别等操作。

总结

提示:这里对文章进行总结: 自己虽然感觉有点小进步,但是实际上也只是成了一个从内存中load文件的方法。后面还需要有一些优化,现在的人脸识别的速度并不高,如果整个工程的功能少一点,一个核用来读取图像流,一个用来做人脸识别可能会更加流畅一点。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3