junan007

  • 2024-12-19
  • 发表了主题帖: 【嵌入式AI挑战营,进阶】从零开始在RV1106上部署人脸识别应用

    本帖最后由 junan007 于 2024-12-19 19:19 编辑 # 一、开发环境的搭建 从包装上看此次活动提供的板子是幸狐LuckFox Pico Max,随板卡一起还有一个3百万像素的摄像头,这样极大的方便了我们进行测试,另外,官方还赠送了一颗带双面胶的钮扣电池。板卡的做工较精良,采用双面设计,核心的部件都在板子的正面,背面是一颗华邦电子的闪存,PCB板上引出了板子支持的GPIO口,同时官方还提供了原理图,动手能力强的可以根据自已项目的实际情况,调整布局,设计出自已的板子。当然,如果提供的是带无线、蓝牙模块和8G存储的就更香了。 1、硬件连接 将摄像头取出,插入板子上网卡后的插槽中,使用USB Type-C线与主机相连后,从板子上指示灯可以看出板子正在启动。 2、系统烧录 根据官方的资料显示,建议到手之后自行烧录新的系统镜像,而且推荐使用buildroot系统,以下描述均默认使用buildroot系统。 首先安装板卡驱动程序[https://files.luckfox.com/wiki/Luckfox-Pico/Software/DriverAssitant_v5.12.zip](https://files.luckfox.com/wiki/Luckfox-Pico/Software/DriverAssitant_v5.12.zip) 下载烧录工具[https://files.luckfox.com/wiki/Luckfox-Pico/Software/SocToolKit.zip](https://files.luckfox.com/wiki/Luckfox-Pico/Software/SocToolKit.zip) 下载官方固件文件[https://pan.baidu.com/s/1Mhf5JMpkFuZo_TuaGSxBYg?pwd=2sf8](https://pan.baidu.com/s/1Mhf5JMpkFuZo_TuaGSxBYg?pwd=2sf8),根据你想使用的系统下载对应的的固件文件,后续你也可以根据自已的需要重新编译系统固件。 上述工具和数据准备好后,在未通电的情况下,按住板子上的BOOT按钮,再连到主机上通电启动。打开准备好的烧录工具,按照官方教程中描述的方法进行系统烧录,如图所示: 3、网络连接 LuckFox Pico Max带了一块网卡,但是我主机上只有一块网卡,而且连到了公司的内网环境,为了减少不必要的麻烦,决定使用NDIS虚拟网卡与板卡直连,开发板默认的IP地址为172.32.0.93,只需要将安装完驱动后多出的虚拟网卡IP地址设置为和它相同的网段,就可以连接了,如172.32.0.100。 使用系统自带的ssh终端命令或者其它支持SSH协议的工具进行连接,默认用户root的密码为luckfox 4、摄像头测试 默认的镜像中自启动了一个官方的IPC应用程序rkipc,在官方资料的摄像头接入部份有详细的描述[https://wiki.luckfox.com/zh/Luckfox-Pico/CSI-Camera](https://wiki.luckfox.com/zh/Luckfox-Pico/CSI-Camera),根据文件中的描述,使用支持RTSP协议的播放器对默认的视频流进行播放rtsp://172.32.0.93/live/0,正常的话即可查看到视频 5、SDK编译 根据后续的使用情况,需要对板卡的SDK进行编译,官方推荐使用Ubuntu 22.04系统进行编译,可以使用虚拟机或者WSL。我使用的是WSL Ubuntu 20.04,其编译的过程与官方文档所描述的基本相同,但需要注意以下几个问题: - SDK源码文件需要复制到WSL系统的原生系统目录下进行编译,不能直接使用Windows系统映射过来的路径(/mnt/d/xxx此种形式)。否则在编译内核阶段出现‘Documentation/KBuild: is a directory’的错误信息而无法正常编译。 - WSL会自动将Windows的PATH环境变量值映射到WSL系统中,会造成编译时提示PATH变量中包含空格的错误信息,可以在命令行中简单粗暴的export PATH=””,或者unset PATH,也可以修改/etc/wsl.conf文件(没有可以手工创建一个)。在其中添加或修改为以下的内容:         ```jsx     [interop]     appendWindowsPath=false     ```         之后在Windows终端下执行wsl -t Ubuntu-20.04 结束wsl进程后,重新再进入wsl的ubuntu系统,即可生效。     - 编译好的固件在output/image下,其它demo程序、脚本等在output/out下,可以根据需要把要测试的程序复制到板子上进行测试,或者使用编译后的固件重新烧录。 至此本地编译环境搭建基本完成。 # 二、Insightface环境构建 活动建议但不限定使用Insightface框架进行模型的部署,为此花了些时间研究了一下Insightface的SDK,从官方的文档中看其SDK支持RV1109和RV1126系列,没有明确标记支持RV1106,但还是抱着试一试的想法对其SDK进行了一些尝试,整体过程如下,感兴趣的可以参考一下。 1、从github上下载Insightface源代码 ```bash git clone https://github.com/deepinsight/insightface.git ``` 2、复制构建脚本 ```bash cd insightface/cpp-package/inspireface/command cp build_cross_rv1109rv1126_armhf.sh build_cross_rv1106.sh ``` 3、修改构建脚本中的部份内容如下: ```bash # 此路径为板卡提供的交叉编译工具链,根据情况进行修改 export ARM_CROSS_COMPILE_TOOLCHAIN=/opt/toolchain/arm-rockchip830-linux-uclibcgnueabihf cmake -DCMAKE_SYSTEM_NAME=Linux \   -DCMAKE_BUILD_TYPE=Release \   -DCMAKE_SYSTEM_VERSION=1 \   -DCMAKE_SYSTEM_PROCESSOR=armv7 \   -DCMAKE_C_COMPILER=$ARM_CROSS_COMPILE_TOOLCHAIN/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc \   -DCMAKE_CXX_COMPILER=$ARM_CROSS_COMPILE_TOOLCHAIN/bin/arm-rockchip830-linux-uclibcgnueabihf-g++ \   -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -flax-vector-conversions" \   -DCMAKE_C_FLAGS="${CMAKE_C_FLAGS} -std=gnu99" \   -DTARGET_PLATFORM=armlinux \   -DISF_BUILD_LINUX_ARM7=ON \   -DISF_ENABLE_RKNN=ON \   -DISF_RK_DEVICE_TYPE=RV1106 \   -DISF_BUILD_WITH_SAMPLE=ON \   -DISF_BUILD_WITH_TEST=ON \   -DISF_ENABLE_BENCHMARK=OFF \   -DISF_ENABLE_USE_LFW_DATA=OFF \   -DISF_ENABLE_TEST_EVALUATION=OFF \   -DISF_BUILD_SHARED_LIBS=ON ${SCRIPT_DIR} ``` 4、编译SDK ```bash // 下载并初始化第三方库 cd .. git clone https://github.com/HyperInspire/3rdparty.git cd 3rdparty git pull // 确保下载第三方库的过程中未出错,根据你的网络情况,可能需要魔法梯子才能正常下载 git submodule update --init --recursive // 开始编译 bash command/build_cross_rv1106.sh ``` 5、成功编译后,会在build目录下找到生成的SDK及测试程序。事与愿违,你可能会和我一样碰到下面的这些问题,记录供参考: - 未定义的ssize_t类型错误。解决方法:修改出错cpp对应的h头文件,增加#include 头文件的包含。 - rknn_init函数参数不匹配错误,解决方法:打开出错的cpp文件,修改函数调用的代码,在最后一个参数0后面再加上一个默认参数NULL ,共有四处。 - 开启编译测试程序开关(ISF_BUILD_WITH_TEST=ON、DISF_BUILD_WITH_SAMPLE=ON)后,在链接时可能会出现undefined reference to ‘__isoc99_fscanf’等错误信息,此时你需要将3rdparty下的OpenCV版本替换,我使用的是女装大佬倪神的Opencv-mobile for luckfox-pico版本,省去了自已编译的时间[https://github.com/nihui/opencv-mobile/releases/latest/download/opencv-mobile-4.10.0-luckfox-pico.zip](https://github.com/nihui/opencv-mobile/releases/latest/download/opencv-mobile-4.10.0-luckfox-pico.zip "https://github.com/nihui/opencv-mobile/releases/latest/download/opencv-mobile-4.10.0-luckfox-pico.zip"),下载后将其解压到cpp-package/inspireface/3rdparty/inspireface-precompile/opencv下,同时修改/cpp-package/inspireface/CMakeLists.txt文件的134,135行,将对应的变量指向新的OpenCV位置。 6、在修改了上述的错误后,就可以正常编译并得到可运行在板卡buildroot系统上的C++ SDK和测试程序。可惜在使用测试程序加载官方模型时出现模型无效的问题,Insightface官方回复SDK没有适配RV1106,只能使用CPU版本,但在关闭RKNN加速后问题依然存在[https://github.com/deepinsight/insightface/issues/2704](https://github.com/deepinsight/insightface/issues/2704),后来确认是模型文件的版本问题,替换了另一个版本的模型文件后,测试程序正常加载。 7、之后可以在示例程序的基础上完成应用层的开发。 # 三、Retinaface、Facenet模型的应用 以下操作均在本地主机上完成,如果你需要训练自已的模型,建议主机上有一块性能不是太差的Nvidia显卡,同时安装好显卡驱动以及对应的CUDA和cuDnn库,略过。如果你没有GPU显卡,也可以使用其他人提供的预训练模型。 1、人脸检测训练环境的搭建 ```bash git clone https://github.com/bubbliiiing/retinaface-pytorch.git cd retinaface-pytorch python -m venv venv   // 创建一个虚拟环境,你也可以使用conda之类的来管理虚拟环境 venv\scripts\active.bat    // 激活虚拟环境 pip install - r requirements.txt   // 安装retinaface-pytorch库依赖 ``` 2、下载或构建自已的训练数据,并将其放置到data文件夹下,修改train.py文件中的参数,如:training_dataset_path数据集标签文件的路径,backbone网络主干结构等。确认无误后执行下列的指令进行模型的训练: ```jsx python train.py ``` 完成训练后,可以在model_data下得到完成训练的Pytorch pth模型文件。 3、人脸检测模型的转换 完成训练后的模型为Pytorch专有格式,如果要在RV1106上使用,需要先转换为ONNX格式,可以使用下列的脚本进行转换: ```python from nets.retinaface import RetinaFace from utils.config import cfg_mnet import torch model_path='model_data/Retinaface_mobilenet0.25.pth' # 上一步完成训练的模型文件路径 model=RetinaFace(cfg=cfg_mnet,pretrained = False) # 创建一个模型对象 device = torch.device('cpu') model.load_state_dict(torch.load(model_path,map_location=device),strict=False) # 模型权重参数加载 net=model.eval() example=torch.rand(1,3,640,640) # 导出时需要执行一次模型前向,使用随机或任意样本即可 torch.onnx.export(model,(example),'model_data/retinaface.onnx',verbose=True,opset_version=9) # 导出为ONNX格式 ``` 保存为export.py后,执行python export.py,即可得到onnx格式的模型文件。 4、人脸特征提取训练环境搭建 ```bash git clone https://github.com/bubbliiiing/facenet-pytorch.git cd facenet-pytorch python -m venv venv   // 创建一个虚拟环境,你也可以使用conda之类的来管理虚拟环境 venv\scripts\active.bat    // 激活虚拟环境, 你可以使用retinaface训练时的虚拟环境,但为了防止库冲突,建议分开 pip install - r requirements.txt   // 安装facenet-pytorch库依赖 ``` 5、下载或构建自已的训练数据,将其放置到datasets目录下,需要注意目录的结构和标签文件的内容。确认无误后与检测模型一样执行python train.py进行模型训练。 6、人脸特征模型的转换 与人脸检测模型一样训练完成后的模型也需要先转换为ONNX格式,脚本如下: ```bash from nets.facenet import Facenet from torch import onnx import torch model_path='model_data/facenet_mobilenet.pth' # 模型文件路径 model = Facenet(backbone="mobilenet",mode="predict",pretrained=True)  # 模型初始化 device = torch.device('cpu') model.load_state_dict(torch.load(model_path, map_location=device), strict=False) example=torch.rand(1,3,160,160) # 给定一个输入 torch.onnx.export(model,example,'model_data/facenet.onnx',verbose=True,opset_version=9) # 导出 ``` 保存为export.py后,执行python export.py, 得到facenet.onnx 7、模型精简和调整 上述导出的ONNX的模型计算图中存在一些冗余的运算符,可以将模型的结构进行简化,优化后的模型更益于部署。可能通过使用onnx-simplifier工具来完成 ```bash // 安装onnx-simplifier pip install onnx-simplifier // 对模型进行简化 python -m onnxsim facenet.onnx facenet_simple.onnx ``` 8、ONNX模型转换为RKNN模型 - 安装RKNN-Toolkit2,根据你Python的版本选择安装的RKNN依赖和安装包 ```bash git clone https://github.com/rockchip-linux/rknn-toolkit2 # Python-3.10 pip install -r rknn-toolkit2/packages/x86-64/requirements_cp310-2.3.0.txt  # 依赖库 pip install rknn-toolkit2/packages/rknn_toolkit2-2.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64  # 安装包 ``` - 模型转换,使用下列的脚本对模型进行转换,脚本如下: ```python import sys from rknn.api import RKNN def parse_arg():     if len(sys.argv) < 5:         print("Usage: python3 {} [onnx_model_path] [dataset_path] [output_rknn_path] [model_type]".format(sys.argv[0]));         exit(1)     model_path = sys.argv[1]     dataset_path= sys.argv[2]     output_path = sys.argv[3]     model_type = sys.argv[4]     return model_path, dataset_path, output_path,model_type if __name__ == '__main__':     model_path, dataset_path, output_path, model_type= parse_arg()     # Create RKNN object     rknn = RKNN(verbose=False)     # Pre-process config     print('--> Config model')     if model_type == 'Retinaface':         rknn.config(mean_values=[[104, 117, 123]], std_values=[[1, 1, 1]], target_platform='rv1103',                                 quantized_algorithm="normal", quant_img_RGB2BGR=True,optimization_level=0)         print("Use retinaface mode")     else:         rknn.config(mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]], target_platform='rv1103')         print('done')     # Load model     print('--> Loading model')     ret = rknn.load_onnx(model=model_path)     if ret != 0:         print('Load model failed!')         exit(ret)     print('done')     # Build model     print('--> Building model')     ret = rknn.build(do_quantization=True, dataset=dataset_path)     if ret != 0:         print('Build model failed!')         exit(ret)     print('done')     # Export rknn model     print('--> Export rknn model')     ret = rknn.export_rknn(output_path)     if ret != 0:         print('Export rknn model failed!')         exit(ret)     print('done')     # Release     rknn.release() ``` 使用方法: python convert.py 其中:数据集文件只需要提供少量的样本图片作为参考,可以从训练数据中抽取。当中记录图片的绝对或相对地址,一个样本一行。 完成后的模型即为RKNN模型,需要注意的是有些ONNX模型中的算子可能RKNN NPU并不支持,这个时候就需要在你的应用程序中去实现这部份。这些算子一般都可以在网上找到代码实现,可以结合官方05_RKNN_Compiler_Support_Operator_List_v1.6.0.pdf文档和 Netron工具进行查看,对于不熟悉网络实现的小伙伴来说,还是有些难度的。所以在模型选择的时候尽量选取NPU支持的网络主干,并在导出ONNX模型后进行精简,能省去不少的麻烦。 至此,得到了可部署于RV1106板卡上的模型文件。 # 四、应用层的整合 官方文档中有许多视觉应用的例子可供参考,可以看出使用RKMPI方式的性能要高于OpenCV,虽然倪神的Opencv-mobile中已经增加了RKNN的支持,但为了减少不必要的麻烦,在RKMPI和RKNN示例程序的基础上进行了修改,基本的代码已经提交到Github上[https://github.com/junanxia/rkface](https://github.com/junanxia/rkface),代码中实现了基本的人脸检测和识别,因为显示屏被其它项目占用,所以就简单的直接在视频上进行了结果OSD叠加,其中只放置了数字和字母的字模。受OSD刷新的影响,多人时看上去不太明显。在人脸识别的过程中,尝试过进行人脸对齐,但对效果的提升并不大(也有可能我的实现有问题),为了减少性能开销,未启用对齐。在相似性计算上简单的使用了余弦相似度,所以程序中的阀值设置比较重要,这部份有提升空间,后续有时间的话会再进行一些改造。 程序的faces目录下为预定义的128维人脸特征,是facenet模型结果归一化后的32位浮点数,你也可以使用图片的方式,只需在程序加载时执行一次特征计算后进行保存。最后程序的运行效果: [localvideo]8919f287c9b602c91b57fd3ae2cbaa88[/localvideo] 以上,仅供参考!

  • 2024-11-21
  • 回复了主题帖: 入围名单公布:嵌入式工程师AI挑战营(进阶)的挑战者们,领取板卡啦

    个人信息已确认,领取板卡,可继续完成任务

  • 2024-11-20
  • 回复了主题帖: 嵌入式工程师AI挑战营(进阶):在RV1106部署InsightFace算法的多人实时人脸识别实战

    申请理由: 1、InsightFace是由旷视开源的、基于Pytorch和MXNet框架的2D&3D深度人脸分析工具箱。当中实现了先进的人脸识别、人脸检测和人脸对齐算法,并针对训练和部署进行了优化。该库提供了C/C++ SDK,支持不同的操作系统和硬件后端,如CPU、GPU、NPU等,应用层开发可以很快速便捷的进行部署。 2、本人多年C++开发,从事视频检测、视频识别相关领域的工作,有幸参与过大型OCR自动化处理工程的实际落地,对于TensorRT、NCNN、TNN等框架在不同应用场景下的使用有一定的经验,曾在Nvidia Jetson Nano、树莓派平台上移植过目标检测、行为分析等模型,但因为其它诸多的因素,还未使用过RV系列的平台,希盼能借此活动对国产硬件平台做进一步的了解,并在后续实际的项目中进行推广和使用。 基本的思路如下: 1、在RV1106开发板中部署平台支持的Linux操作系统,如适用于嵌入式硬件的Buildroot系统等。 2、使用RV1106平台支持的交叉编译工具链对需要使用到的环境依赖进行编译,主要涉及到Opencv、RKNN等 3、摄像头的基本调试,主要测试驱动是否正常,视频帧能否正常获取等。 3、使用预训练模型对RV1106进行硬件能力评估,根据评估情况结合项目中功能指标的要求,挑选适合的网络主干,如ResNet、MobileNet、DenseNet等。 4、使用RKNN-Toolkit对模型进行转换、量化等优化工作,根据其性能表现、内存表现选取最终的模型结构及适合的模型精度(int4、int8、int16精度选择)。 5、将选取的模型应用到系统中,系统主体流程简述为:使用Opencv从摄像头中获取单帧图像(根据情况适当的进行抽帧)->使用模型对人脸进行检测、对齐->使用基本的分类算法对人脸进行分类输出->结果数据合成输出。 应用场景: 门禁打卡

  • 点评了资料: 超图解 ESP32 深度实作 (赵英杰)

最近访客

< 1/1 >

统计信息

已有6人来访过

  • 芯积分:11
  • 好友:--
  • 主题:1
  • 回复:2

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言