RV1126B边缘人脸识别全攻略:从模型转换到板端部署

发布时间:2026/9/15 8:59:37
RV1126B边缘人脸识别全攻略:从模型转换到板端部署 做边缘端人脸识别瑞芯微这颗RV1126B在EASY EAI平台上的方案我前前后后折腾了小半年踩了不少坑也跑通了从模型转换、板端推理到门禁机逻辑的整条链路。这块板子的定位很明确用更低的功耗和成本把本地人脸识别、抓拍、比对这些事在端侧搞定不依赖云端。如果你正准备做门禁考勤、闸机伴侣、无感通行这类设备或者想把手头的人脸识别算法部署到边缘硬件上这篇文章应该能帮你少走很多弯路。我会从硬件选型、环境烧录、算法部署、板端实现、调优排障这几个方向把RV1126B做人脸识别的完整思路和实操细节一次讲透。内容偏实战不绕弯子代码和参数都尽量给到可以直接抄作业的程度。1. 先搞清硬件底子RV1126B和EASY EAI能干什么1.1 芯片规格与人脸识别任务的匹配逻辑RV1126B是瑞芯微面向IPC和边缘AI的一套SoC方案延续了RV1126的架构思路四核Cortex-A7作为主控内置NPU算力在2.0 TOPS附近集成ISP和视频编解码单元。做算法部署的人可能对这个算力数字没概念我换个说法2.0 TOPS的INT8算力跑一个轻量级人脸检测网络比如简化版RetinaFace或SCRFD加一个MobileFaceNet特征提取网络两路模型串行推理单次完整人脸识别流程大概能控制在80到150毫秒这个速度对门禁闸机场景完全够用。很多人会纠结为什么不用RK3588这种更高算力的平台因为做人脸识别门禁机这类产品成本、功耗、体积是硬约束。RK3588算力强但主板成本和散热要求完全不是一个量级。RV1126B的功耗控制得比较好被动散热甚至无外壳散热都能稳定跑这是它能在人脸识别门禁、考勤机上到处出现的原因。芯片内置的ISP也是容易被忽略但非常重要的一环。做门禁机的人都知道逆光、暗光、强光下识别率波动特别大。RV1126B的ISP支持宽动态、去噪、自动曝光配合好的传感器能在比较恶劣的光照条件下给算法喂到相对干净的画面。我实测下来同样的模型在ISP参数调好和没调的情况下识别率差距能到5个百分点以上。1.2 EASY EAI平台给了什么起步条件EASY EAI围绕RV1126B做了一套完整的硬件和SDK方案板上引出了MIPI CSI摄像头接口、千兆以太网、USB、显示接口基本覆盖了做一台人脸识别终端需要的全部外设接口。SDK里比较核心的几个部分是Linux BSP移植好的内核和根文件系统、RKNN的板端推理运行时、摄像头采集示例、RTSP推流示例以及一套官方的人脸识别demo。我的建议是如果你第一次接触这个平台千万别一上来就自己从零写人脸识别逻辑先把官方demo编译烧录进去跑通一个完整的“摄像头抓拍-人脸检测-特征提取-屏幕显示结果”的流程再考虑替换成自己的模型和业务逻辑。这里还要多说一句平台定位问题。同门师兄弟里RV1106/RV1103是更轻量的方案算力和接口规模都小适合做低功耗猫眼、可视门铃这类场景RK3568则算力更高、接口更丰富适合做需要同时跑人脸识别加其他业务比如车牌识别、视频结构化的设备。RV1126B卡在中间主打“够用且便宜”人脸识别是它最典型也最成熟的应用形态。2. 环境搭建与系统烧录让板子先跑起来2.1 开发机环境准备和SDK版本对应关系RV1126B的开发环境分两头一头是PC端负责模型转换和交叉编译另一头是板端负责运行。PC端我推荐用Ubuntu 18.04或20.04的64位系统开发机上需要装好RKNN-Toolkit相关依赖。关于RKNN-Toolkit的版本这块要特别留意。RV1126B这类芯片对应的转换工具链和我后面会提到的RK3588用的RKNN-Toolkit2不是同一个分支。也就是说你在PC上做模型转换时要用芯片SDK配套的rknn-toolkit版本以EASY EAI SDK里自带的为准。我见过太多人把rknn-toolkit2的模型直接拿过来加载结果板端init直接报错其实是工具链版本不匹配。安装环境时另外两个容易出问题的点一是模型转换阶段需要用到TensorFlow或PyTorch等框架来加载原始模型依赖库版本冲突比较常见建议用虚拟环境隔离二是转换工具里的numpy、opencv、onnx等版本要匹配否则会出现莫名其妙的报错。我自己的习惯是把开发机的Python环境固定下来不随便升级包。2.2 烧录工具、步骤和踩过的坑烧录这块在Windows下用瑞芯微驱动助手加RKDevTool工具在Linux下可以用upgrade_tool命令行工具。核心动作就三步安装驱动、让板子进入Loader模式、选择镜像烧录。具体操作为先安装瑞芯微驱动助手安装完把开发板用USB线连接到电脑。按住板上的recovery按键有的板子是烧录按键不放然后给板上电或按下复位键进入Loader模式。打开RKDevTool正常情况下会识别到一个Loader设备然后按照SDK文档里的分区表配置选择uboot、boot、rootfs、recovery等镜像文件点击执行开始烧录。烧录完成后断开USB重新上电启动。这中间有几个坑我反复遇到。第一个是设备不识别多半是驱动没装好或者USB线质量太差。瑞芯微的烧录对USB线材比较敏感建议用带屏蔽的短线不要用那种又长又细的充电线。第二个是烧录到一半卡死这种一般是文件分区表配置错了或者镜像文件和当前工具版本不匹配重新检查一下分区配置文件。第三个是板子启动后串口无输出先检查串口电平是否匹配RV1126B调试串口一般是3.3V电平用了5V的USB转串口模块可能会出问题。从经验来说新板子到手别急着改代码先把官方固件烧进去验证串口、网络、摄像头、NPU这几个基础资源都正常再做后面的开发这样能把问题范围控制住。3. 从模型到端侧部署人脸识别算法的完整链路3.1 算法选型检测和识别分开看人脸识别在端侧落地严格来说包含两个独立模型人脸检测模型和人脸识别模型。前者负责在图像里找到人脸框和关键点后者负责把对齐后的人脸图像转成特征向量。人脸检测方面工程上常用的开源方案有RetinaFace、SCRFD、CenterFace以及YOLOv5-Face。选择标准很简单在板端NPU上要跑得动。RetinaFace的MobileNet版本是个比较稳的选择SCRFD在精度和速度的平衡上更好一点但可能需要对模型结构做裁剪或在转换时处理一些不支持的算子。CenterFace更轻适合对精度要求不算极端的场景。人脸识别网络方面MobileFaceNet配合ArcFace或CosFace损失函数训练得到的模型是最常见的选择输出维度一般是128维或512维特征向量。这里注意一点人脸识别和分类不一样我们要的不是分类层的输出而是骨干网络输出的特征向量后面接的FC层在部署时通常要去掉。热词里提到“开源免费商用的人脸识别模型”这部分我多说两句。InsightFace开源了ArcFace的训练代码和推理代码里面有MobileFaceNet等backbone的实现也开放了不少公开数据集的训练配置。但要注意“开源免费商用”这个概念代码本身是开源的模型权重则要看你用的是哪份、什么许可证商业产品落地前最好自己梳理清楚。如果想要省心也可以完全自己准备数万人的人脸数据集用ArcFace训练一个MobileFaceNet可控性最高。3.2 RKNN模型转换与INT8量化的关键细节模型转换是端侧部署最容易翻车的一步。PC上的PyTorch/ONNX模型不能直接在板端NPU跑必须要转成RKNN格式。一个典型的ONNX转RKNN流程是这样的from rknn.api import RKNN rknn RKNN() # 配置输入输出的归一化参数target_platform填芯片对应的平台 rknn.config( mean_values[[123.675, 116.28, 103.53]], std_values[[58.395, 58.395, 58.395]], target_platformrv1126 ) # 加载onnx模型 rknn.load_onnx(modelmobilefacenet.onnx) # 量化构建dataset.txt里每行写一张用于校准的图片路径 rknn.build(do_quantizationTrue, datasetdataset.txt) # 导出为rknn文件 rknn.export_rknn(mobilefacenet.rknn)这里的mean和std必须和你训练时用的一致。很多人模型转换后精度大跌其中一类原因就是这里填了默认的ImageNet参数而模型训练时的预处理用的是别的均值和方差。另外量化用的校准图片一般选20到50张覆盖不同光照、不同人种的图就够了不要拿一个类别的图去校准否则量化后的特征分布会偏心。算子不支持是另一个高频问题。RV1126B的NPU对算子支持是有一份清单的遇到不支持的算子转换时会报错或自动切成CPU执行。自动切CPU在功能上没问题但速度会明显变慢因为CPU跑神经网络效率太低。如果检测到某个算子被放到CPU执行建议回头修改模型结构把不支持的算子替换成NPU支持的等价实现比如把某些动态尺寸的操作固定下来或者把不常用的激活函数换成ReLU这类NPU原生支持的。4. 板端人脸识别程序的核心实现4.1 整体流程从摄像头到识别结果板端的人脸识别程序本质是一条流水线采集、检测、对齐、特征提取、比对、输出。我用大白话描述一下这条链路的顺序和逻辑摄像头采集一帧RGB图像这一步通常用V4L2接口拿MIPI CSI摄像头或USB摄像头的画面。把图像缩放后送入人脸检测模型得到人脸框坐标和关键点坐标。根据关键点做人脸对齐将人脸区域通过仿射变换校正到标准尺寸比如112x112或96x96。将对齐后的人脸图像送入人脸识别模型得到特征向量。拿这个特征向量和本地特征库里的向量逐一计算相似度取最大相似度。如果最大相似度超过设定阈值识别成功否则判定为陌生人。注意这里说的“缩放后送入检测模型”和“对齐后送入识别模型”两次输入的尺寸和预处理完全不一样。检测模型输入一般是640x640或416x416识别模型输入是112x112。很多第一次做端侧人脸识别的人会在这一步搞混导致识别率极低。4.2 板端RKNN推理代码的骨架RKNN板端推理的C接口逻辑不算复杂核心是init、set input、run、get output这几步我贴一个简化版的推理骨架#include rknn_api.h static rknn_context detect_ctx, face_ctx; int rknn_face_inference(unsigned char *img, int width, int height, float *embedding_out) { // 检测模型推理 rknn_input det_in[1]; det_in[0].index 0; det_in[0].type RKNN_TENSOR_UINT8; det_in[0].size width * height * 3; det_in[0].fmt RKNN_TENSOR_NHWC; det_in[0].buf img; rknn_inputs_set(detect_ctx, 1, det_in); rknn_run(detect_ctx, NULL); rknn_output det_out[1]; det_out[0].want_float 1; rknn_outputs_get(detect_ctx, 1, det_out, NULL); // 解析输出得到人脸框和关键点并执行仿射变换 // ... // 识别模型推理输入为对齐后的人脸图像 aligned_img rknn_input face_in[1]; face_in[0].index 0; face_in[0].type RKNN_TENSOR_UINT8; face_in[0].size 112 * 112 * 3; face_in[0].fmt RKNN_TENSOR_NHWC; face_in[0].buf aligned_img; rknn_inputs_set(face_ctx, 1, face_in); rknn_run(face_ctx, NULL); rknn_output face_out[1]; face_out[0].want_float 1; rknn_outputs_get(face_ctx, 1, face_out, NULL); memcpy(embedding_out, face_out[0].buf, 128 * sizeof(float)); rknn_outputs_release(detect_ctx, 1, det_out); rknn_outputs_release(face_ctx, 1, face_out); return 0; }这里有几个容易被忽视的细节。want_float设为1时工具会把INT8的NPU输出反量化为float方便直接算相似度代价是增加一点转换开销如果你的特征向量本身对浮点精度不敏感也可以直接拿INT8输出减少一次拷贝。buffer的分配要提前做好不要在推理循环里频繁malloc和free板子的内存碎片会越来越严重。还有一点两个模型建议分开两个rknn_context加载不要共用一个context这样可以在后续用两个线程分别跑检测和识别把流水线并行起来。4.3 特征库、相似度计算和比对策略识别模型输出128维特征向量后比对策略直接决定产品的使用体验。特征库我建议在板端用SQLite存储字段就两个人员ID、特征向量。SQLite在嵌入式Linux上是标配简单可靠支持事务万一程序掉电重启数据也不会坏。如果人员规模不大几百人以内也可以直接启动时把特征库全部加载到内存里比对时纯内存遍历速度最快。相似度计算方面人脸识别模型一般用余弦相似度。两个128维向量的余弦相似度计算开销极小1000个人的库线性扫描一遍也就几十万次乘加在Cortex-A7上消耗不到几毫秒。所以对门禁机这种单机场景完全不用考虑复杂的ANN检索。如果是要做“边缘人脸识别 大量数据”这种场景比如上万人甚至几十万人的库那就得在PC端或服务器端做特征归档板端只负责抓拍提取特征后上传比对放到后端。阈值这个地方不同模型、不同训练数据差异很大。我自己的经验是MobileFaceNetArcFace这套组合在正常光照下同一个人的余弦相似度通常在0.6到0.8之间不同人的相似度一般在0.2以下阈值取0.5到0.6之间比较合理。做门禁考勤这种误识率要求高的场景阈值可以往高了调比如0.62宁可不识别也不要认错人做无感通行这种体验优先的场景阈值可以适当降低到0.48减少漏报。5. 实际调优与踩坑记录识别率、速度、稳定性5.1 识别率提升的实战手段识别率上不去千万别只盯着模型换模型。我排优先级的话硬件和图像质量排第一预处理对齐排第二模型本身排第三。先说图像质量。门禁机场景最大的敌人是逆光。RV1126B的ISP如果没调好人脸在逆光下就是一片死黑什么模型都白搭。建议优先把ISP的宽动态打开做自动曝光和自动白平衡的调试必要时加补光灯。我在项目里加了一圈850nm红外补光夜间识别率从惨不忍睹拉到了和白天差不多的水平。其次是对齐的准确性。人脸识别模型对对齐极其敏感同一个人的脸对齐偏了2个像素相似度可能从0.7掉到0.5以下。所以检测模型输出的关键点必须准仿射变换的目标点坐标也要设置合理。多数开源模型用的是五点和标准112x112模板对齐目标点坐标别自己随便改直接用模型作者提供的meta文件里的设定。第三是阈值和距离策略。在实际场景里会不断出现同一个人的不同角度、表情、妆造变化如果每次识别都走同样的阈值很容易把“不太好认”的合法用户拒之门外。更好的做法是客户端维护一个短期识别状态比如连续10帧中出现3帧识别为同一个人就判定识别成功偶尔一帧相似度低于阈值但接近阈值时不急着判定陌生人等后面的帧补充判断。这种时序上的平滑策略在门禁机上的体验提升非常明显。5.2 推理速度优化让流水线转起来推理速度的瓶颈往往不在NPU算力而在数据搬运和流程串行。我优化完后检测模型单帧NPU推理约40毫秒识别模型约25毫秒但最初整个流程跑下来要300多毫秒瓶颈就在CPU读图、缩放、格式转换、等待这些环节上。优化手段主要有三个把摄像头采集和算法处理放在两个线程采集线程只负责抓图和缓冲算法线程负责推理。这样推理时间被采集时间吸收整体帧率能提升一倍。使用NV12等摄像头原生格式直接喂给部分检测模型省去RGB转换。如果模型输入必须是RGB再用RGA硬件加速做颜色空间转换不要用CPU软转。模型输入分辨率不要盲目求大。检测模型用640x640对一副人脸画面的检测能力已经足够再高也只是增加计算量识别模型对齐后112x112是标准尺寸160x160的输入不会带来显著精度提升但推理耗时可能翻倍。零拷贝也是瑞芯微NPU的优化点。rknn_init之后可以通过buffer分配接口创建DMA buffer再把摄像头数据直接映射到这个buffer里省掉一次memcpy。这个优化在数据量大的时候收益明显但代码复杂度会上升建议先把功能跑通再考虑。5.3 常见问题速查表我把实际调试中遇到的问题整理成了一张速查表供大家排查时对照。现象可能原因排查和解决办法烧录时PC识别不到设备驱动没装好、USB线质量差、没进Loader模式重装瑞芯微驱动助手换短线按住recovery键再上电板端rknn_init返回错误RKNN模型版本与板端SDK不匹配用SDK自带rknn-toolkit重新转换模型确认target_platform模型推理结果全为0或固定值输入buffer未正确填充或通道顺序不对检查rknn_input的size和fmt确认RGB还是BGR检测不到人脸图像翻转、输入尺寸和模型不匹配检查摄像头方向确认模型输入宽高与转换时一致识别率低且不同人之间相似度高归一化参数不对、量化校准集太单一核对mean/std与训练一致校准图覆盖多光照多角度程序跑一段时间后内存涨推理循环里不断分配buffer未释放推理前分配好固定buffer结束后调用rknn_outputs_releaseNPU利用率上去但整体帧率低流水线串行等待CPU处理慢采集与推理分线程用RGA做图像缩放和格式转换这套表是长期调试攒下来的基本覆盖了RV1126B人脸识别最常见的故障方向。遇到问题先按表排查大多数情况能定位到具体环节。最后再分享一个我个人的经验量产项目里不要把阈值、补光策略、图像缩放尺寸这些参数硬编码在代码里全部做成调试接口或配置文件。实际部署时不同现场的光线环境差异极大板子装到机箱里和裸板测试的散热、镜头角度都不一样能现场调参意味着你少跑好几趟现场。另外方案初期的模型选型别追求最先进先用最成熟、SDK支持最完善的公开模型把整条链路跑通再逐步替换成自训练模型这个顺序能让你在调优时少很多烦恼。