
我把这套流程从服务器搬到RK3588板端前前后后折腾了两周多。一开始以为就是跑通一个demo实际做下来才发现SuperPointLightGlue这套组合在边缘端的坑比想象中多算子兼容、量化精度、CPU和NPU的负载分配每一个环节都能卡你半天。这篇博文把整个实现过程和性能测试结果整理出来包括模型转换、定位链路搭建、量化取舍以及实际跑出来的数据给同样想在RK3588上做特征匹配定位的朋友一个直接可参考的版本。先说清楚这个项目是干什么的。目标定位这里不是指目标检测框而是通过特征点匹配拿到目标在图像中的精确位置和姿态。具体来说用SuperPoint提取模板图和查询图的特征点与描述子用LightGlue做特征匹配再用RANSAC加单应矩阵解算目标位置。整个过程全部在RK3588板端本地运行不依赖服务器。适合做机器人抓取、增强现实、工业视觉定位这类场景的开发者参考也适合刚接触RKNN模型转换、想在NPU上跑自研视觉模型的人。我会把每个环节的代码思路、参数设置和踩坑记录都写出来。1. 项目概述与方案选型1.1 为什么在边缘端做特征匹配定位先聊需求。很多视觉定位任务之前是放在x86服务器上跑的高分辨率图像、大模型、GPU加速效果很好但到了实际部署环节就尴尬了。工业现场的相机工控机离服务器可能隔着几条产线网络抖动一下定位就断了移动机器人更是只能在板端本地计算不可能为了一个定位功能专门配一台带GPU的机器。所以边缘端实时跑视觉定位是一个很真实的需求。那为什么选特征匹配而不是直接上目标检测网络检测网络给的是物体框中心点加宽高精度取决于锚框和回归头大概只能到像素级但很多场景要的是亚像素级的角点位置或者要知道目标相对相机的精确角度检测框满足不了。特征匹配方案通过特征点一一对应再用几何约束求解单应矩阵输出的是完整的4点定位结果可以做精确的姿态估计。而且SuperPoint这类学习的特征点在光照变化、视角变化和纹理缺失情况下的鲁棒性明显优于SIFT和ORB这种手工特征调参成本也低很多。选RK3588有三个直接原因。首先是算力NPU官方标称6 TOPSINT8下跑一个轻量级特征提取网络绰绰有余其次是CPU性能4个A76大核加4个A55小核跑LightGlue这种计算量中等偏上的Transformer模型比同类ARM板子稳得多最后是生态RKNN工具链对PyTorch转ONNX再转RKNN的流程支持比较完善社区资料也多真遇到问题不至于一个人死磕。1.2 为什么是SuperPoint加LightGlue组合SuperPoint是一个自监督训练的特征点提取网络。它最大优势是训练方式先用合成图像学兴趣点检测再用单应变换生成伪标签做自监督训练最后能在真实图像上提取出重复性很高、分布很均匀的特征点。网络上分三个分支共享一个VGG风格的编码器然后接兴趣点解码器和描述子解码器输出每个像素位置的特征点概率分布和256维描述子向量。LightGlue是SuperGlue的轻量化替代方案。两者核心思路一样用Transformer的注意力机制在两张图的特征点之间做匹配而不是像传统方法那样只比较描述子距离。但SuperGlue太重了在CPU上跑一帧要几秒钟板端完全不可用。LightGlue做了几个关键改进更轻量的编码器、自适应深度机制也就是模型会根据匹配难度自动决定计算多少层Transformer简单场景提前退出复杂场景才加深。这个特性在边缘端价值很大平均推理时间能省下一半。另外它对匹配点数量也更宽容支持输入不同数量的特征点做匹配。整体精度只比SuperGlue略低但速度快了一个数量级以上。1.3 目标定位的完整链路整个系统的流程不复杂但每个环节都有讲究。模板图在启动时离线提取一次特征存下特征点坐标和描述子。运行时每来一帧查询图先走SuperPoint提取特征点然后和模板图的特征一起送入LightGlue做匹配输出匹配对应关系再用OpenCV的RANSAC求解单应矩阵单应矩阵再把模板的目标区域映射到当前帧上得到定位框或角点。听起来简单部署到板端就要重新思考资源分配。我最终的方案是SuperPoint主体上NPU跑INT8量化前后处理和特征解码全部留在CPU侧LightGlue只支持部分算子RKNN无法完整转换所以放在CPU侧用ONNX Runtime跑FP32。这样NPU和CPU形成流水线NPU跑提取CPU同时跑上一帧的匹配和后处理整体吞吐更高。具体怎么拆、怎么转、每个环节的耗时数据接下来细讲。2. 环境搭建与模型转换2.1 RK3588部署环境准备先说环境。板端系统是Ubuntu桌面版还是服务器版影响不大但内核必须支持RKNPU驱动。跑推理需要两套东西开发机上用RKNN-Toolkit2做模型转换和仿真板子上用RKNN Runtime做实际推理。RKNN-Toolkit2的安装有几个前提条件Python版本建议3.8到3.10依赖库要单独装最好用虚拟环境隔离。模型转换在x86的docker容器里做比较省心官方镜像自带全套依赖能绕开一堆编译报错。板子上的RKNN Runtime则是一个so库加配套头文件安装流程很简单把库路径加进/etc/ld.so.conf.d/执行ldconfig就完事。板端我是先从官方示例库编译跑通了yolov5的demo确认整个NPU链路打印出rknn_init success的日志才继续往下做自己的模型。一个容易忽略的点是工具链版本必须对齐。RKNN-Toolkit2是PC端的转换工具RKNN Runtime是板端的推理库两者的版本必须严格对应否则转换出来的rknn模型在板端加载会直接报版本不匹配。建议直接查官方版本的对应表不要盲目升级到最新版。2.2 SuperPoint转ONNX再转RKNNSuperPoint的PyTorch权重转ONNX没什么坑直接torch.onnx.export就能出图。但转之前一定要把输入尺寸固定下来。RKNN转换时最稳妥的方式是固定shape输入动态shape很容易触发算子不支持或者性能回退。我的输入分辨率设成1x3x480x640为什么是这个尺寸后面性能部分会说。转ONNX时还要注意把模型的输出明确指定。SuperPoint原版有三个输出半稠密特征点得分图和描述子图。原模型的输出是一个Bx65xHxW的得分张量加一个Bx256xHxW的描述子张量65那个维度对应8x8区域加一个dustbin。我选择在ONNX导出时保留这两个输出不做任何后处理整合。因为后处理跨了很多算子和维度变换放到NPU里要么不支持要么性能极差不如导出后自己在CPU上写。真正麻烦的是转RKNN这一步。直接用原模型转换会报一堆算子不支持我遇到的主要问题有三个第一个是grid_sample。部分SuperPoint实现里描述子需要用到双线性插值或者grid_sample来对齐坐标RKNN对grid_sample的支持有限转换时直接报错。解决办法是改网络实现把需要grid_sample的部分去掉改为在CPU后处理里做插值这个不影响结果只是把计算挪了个位置。第二个是channel shuffle。某些SuperPoint变体用了shuffle操作来混合通道信息RKNN虽然不报错但性能很差实测可能比CPU慢。遇到这种情况建议直接改写网络结构用1x1卷积替代shuffle再做精度验证。第三个是描述子的归一化。论文里描述的L2归一化最好挪到后处理做。因为FP32的归一化在INT8下会放大误差而且在NPU上L2范数运算也不高效。所以我在导出ONNX时就砍掉了归一化层输出原始描述子拿到CPU上自己归一化。转RKNN的配置里量化方式选int8量化数据集准备200到300张和实际场景接近的图就够了。这里有个细节量化校准集不要全是模板图要混入不同光照和角度的查询图否则NPU推理结果在真实使用场景下偏差会很大。校准集数量太少会导致量化参数过拟合到个别图片上。转完的rknn模型可以用RKNN-Toolkit2自带的模拟器先跑一遍和PyTorch输出做对比。模拟器的速度没有参考价值但数值精度基本能反映板端的情况。我在这一步就发现描述子输出的余弦相似度只有0.985左右通过调整量化数据集修正到了0.99以上这个阈值是我最终定位成功率的分水岭。2.3 LightGlue在CPU侧的部署策略LightGlue不是完全不能上RKNN而是完整转换的性价比太低。它里面有LayerNorm、GELU、多头的自注意力机制还有一些自定义的掩码操作这些算子在RKNN上要么转换失败要么一层性能慢到离谱结果就是推理时间反而比CPU还差。所以我的策略很直接LightGlue留在CPU上跑用ONNX Runtime作为推理引擎。LightGlue支持ONNX导出官方代码里有现成的导出脚本。但有两个问题要在导出前解决。第一是动态shape。LightGlue的输入是两个特征点集合点数是不固定的模板图可能提了1500个点查询图可能只提了800个点。ONNX导出时我直接导出了动态维度让序列长度可变。ONNX Runtime完全支持动态维度只是板端推理时会有额外的内存分配开销可以通过预先分配缓冲池来缓解。第二个问题是LightGlue的注意力计算复杂度是O(N²)N是特征点数量。在CPU上跑2000x2000的点积注意力一次就要几百毫秒完全不可接受。我的做法是限制输入点数SuperPoint提取特征点后按置信度排序只保留前1024个实测对定位精度影响很小但推理时间能降一半以上。如果目标很小或者纹理稀疏1024个点完全够用如果场景特别复杂可以适当放宽到1536但要做好耗时上升的心理准备。ONNX Runtime在RK3588上要启用多线程。Ort::SessionOptions里设置线程数、开启内存优化还有一个容易被忽略的参数是SetIntraOpNumThreads和SetInterOpNumThreads要区别对待。我实测下来单独设8个intra线程效果最好inter线程开多了反而因为线程切换导致性能下降。LightGlue推理还有一个CPU亲和性优化的空间。LightGlue中间有大量矩阵乘法ONNX Runtime默认用的是自己编译的通用内核如果板端支持OpenBLAS或oneDNN可以重新编译ONNX Runtime以启用底层加速库推理时间能再降15%到20%。我们用的镜像里没有现成的加速库就没胡折腾但如果你有时间这个优化的性价比很高。3. 定位流程实现与关键细节3.1 SuperPoint前处理与后处理对齐这个环节是精度对不齐的重灾区。先说前处理SuperPoint的训练数据是ImageNet风格的归一化也就是减均值除方差均值是[0.485 0.456 0.406]方差是[0.229 0.224 0.225]。如果你在CPU的PyTorch测试时用的是这个归一化那RKNN的输入预处理也必须完全一致。RKNN的img2bgr接口虽然方便但它只做减均值除方差的std操作且默认按BGR通道处理和PyTorch的RGB顺序不一样这个顺序问题经常被忽略。我是干脆在C侧自己写预处理把OpenCV读到的BGR图像转RGB再按像素做归一化避免RKNN内置插件引入不确定性。输入尺寸方面我之前说固定成480x640。这个尺寸不是随便定的首先它接近常见相机分辨率1920x1080的1/2缩略图信息保留足够其次它正好是8的整数倍SuperPoint内部有两次下采样最终特征图是60x80避免了边缘padding带来的伪特征点最后它的大小能让NPU推理时间控制在45ms以内。后处理是整个精度问题的核心。SuperPoint的得分头输出形状是1x65x60x8065代表8x8的区域加一个dustbin通道。后处理要做的是把65通道reshape成641的分布对前64个通道做softmax然后丢弃dustbin再把得分映射到原始的8x8网格上。这里有个细节softmax要在641的维度上一起做而不是单独对64做。因为网络设计时dustbin是和64个有效通道竞争概率的分开softmax会改变特征点的置信度分布。代码写出来大概是这个效果// 输入: score_map shape [1, 65, 60, 80], 内存连续, float32 // 输出: scores [60*80], 以及处理后的8x8亚像素得分 for (int y 0; y 60; y) { for (int x 0; x 80; x) { const float* ptr score_map (y * 80 x) * 65; float max_val -1e10f; for (int c 0; c 65; c) max_val fmax(max_val, ptr[c]); float sum_exp 0.0f; for (int c 0; c 65; c) sum_exp expf(ptr[c] - max_val); dustbin_prob expf(ptr[64] - max_val) / sum_exp; cell_score 1.0f - dustbin_prob; // 低于阈值的设为0 if (cell_score 0.015f) continue; // 在8x8区域内找局部峰值记录坐标和得分 } }描述子后处理更直接输出是1x256x60x80每个空间位置对应一个256维向量。从NPU拿到原始输出后要先按位置取出来再对整个矩阵做L2归一化。这里又一个容易踩的坑RKNN的INT8推理输出是反量化后的float32反量化的scale是每个通道单独给的所以描述子的256个通道可能有各自的量化参数直接用RKNN输出的数据做L2归一化没问题但如果中间做了任何重排reshape量化参数就套错了。特征点坐标最终要映射回原始图像分辨率。SuperPoint输出的坐标是60x80的特征图坐标放缩倍数是8所以原始坐标就是8 * (feature_coord 0.5)你可以理解成特征图中心对齐到原图像素坐标。如果输入做了等比例缩放还要再除以缩放系数。坐标映射错一个像素RANSAC阶段往往还看不出来但最终的定位框会偏半个角点这个误差很要命。3.2 LightGlue匹配与自适应迭代LightGlue的输入是三样东西查询图的特征点和描述子、参考图的特征点和描述子。它的输出是匹配结果矩阵和置信度。板端推理时我把前面SuperPoint得到的特征点坐标和归一化描述子直接作为输入传入ONNX Runtime session。先要理解LightGlue自带的置信度机制。它在每个Transformer层之后都会根据当前层的匹配置信度判断是否可以提前停止。如果特征点很独特、视角变化很小可能只跑2层就输出了如果场景有重复纹理才会跑完全部9层。这个机制在服务器上能省多少算力不好说但在RK3588的CPU上感知非常明显我实测平均推理层数在4到6层之间端到端时间能省30%到50%。自适应深度也会带来一个问题每次推理的层数是动态的所以ONNX Runtime的单次推理耗时方差很大。简单场景可能60ms复杂场景能冲到180ms。在做性能测试的时候不能只看平均帧率要看P95甚至P99的延迟否则实际运行时遇到复杂纹理场景会出现明显卡顿。匹配结果里偶尔会有少量误匹配表现为交叉的匹配线。LightGlue有内置的置信度过滤输出会给出每个匹配的得分我取了0.2这个阈值过滤低分匹配。阈值调太高会丢掉正确的匹配导致RANSAC点数不够调太低会放进来一些错误匹配增加RANSAC迭代次数。0.2是我试了几个值之后效果最稳的起始值具体可以根据你的场景微调。还有一个小技巧值得说LightGlue对描述子做内积前内部会把描述子做归一化。所以如果你在SuperPoint侧已经做了L2归一化再把数据送进去相当于做了两次归一化不影响结果但会多一次向量除法。如果对性能敏感可以在导出ONNX时把LightGlue内部冗余的归一化层裁剪掉。这个改动不影响精度因为归一化两次的数学结果完全一样。不过如果不是特别在意那几毫秒建议维持原版结构少改动模型降低出错概率。3.3 目标定位解算与RANSAC拿到LightGlue的匹配点对之后就要用几何约束解出目标位置。平面目标定位用单应矩阵就够。我用OpenCV的findHomography配合RANSAC求解核心参数有三个RANSAC重投影误差阈值、迭代次数和置信度。默认阈值是3像素在480x640的输入分辨率下3像素偏严了因为分辨率降低了定位误差天然会大一些。我手动调成5像素后内点率从38%提升到55%最终的定位框反而更稳。RANSAC迭代次数默认值是2000对于不到200对的匹配点2000次足够不用额外加。单应矩阵解出来之后把模板图的四个角点投影到当前查询图上就得到目标定位结果。如果要做的是6DoF位姿估计而不是平面定位可以把findHomography换成solvePnPRansac输入目标3D点和对应的2D图像点还有相机内参输出旋转向量和平移向量。流程思路完全一致只多了一个相机标定前置条件。一个容易出问题的地方是单应矩阵的符号和方向。OpenCV的findHomography默认是从第一张图映射到第二张图如果你把模板图和查询图的参数顺序搞反了投影结果会完全错乱。建议在写完代码后先做一个最简单的验证用模板图本身作为查询图应该输出单位矩阵定位框应该和模板原图完全重合。这个测试能一次性排除很多低级错误。4. 性能测试与优化实录4.1 测试环境与指标定义性能测试的硬件平台是RK3588开发板8GB内存版本SoC频率策略设置为schedutil操作系统的电源策略是performance。这里必须说明节电模式会让A76核心频率直接从2.4GHz掉到1.8GHzLightGlue的耗时能差40%以上所以测试前务必锁定CPU频率策略否则数据没法对比。我定义了这几个指标指标含义端到端延迟从查询图输入到输出定位框的完整耗时分阶段耗时SuperPoint提取、后处理、LightGlue匹配、RANSAC四段各自耗时P50/P95延迟反映延迟分布的稳定程度CPU占用率4个大核的整体占用百分比NPU占用率通过rknn runtime查询到的NPU核心利用率测试素材用实际场景拍摄的模板图和查询图共收集了5组目标、每组20帧查询图覆盖不同光照和视角。这样测出来的数据才有意义而不是拿几张网上图片模拟一下。4.2 耗时分布与数据表现这是整个项目最核心的产出。在480x640输入、RGBA8888格式、SuperPoint INT8量化、LightGlue FP32 CPU推理、特征点上限1024的条件下实测典型数据如下阶段耗时说明SuperPoint NPU推理38msINT8量化三核NPU中单核调用特征点后处理10ms包括softmax、峰值检测、描述子归一化LightGlue匹配105ms平均6层自适应深度FP328线程RANSAC与投影4ms平均150对匹配点端到端合计157ms约6.4FPS这个数据比预期的好。我最初方案是SuperPoint也跑CPU结果CPU频率即使拉满SuperPoint单帧也要接近90ms加上LightGlue完全跑不动。切到NPU之后SuperPoint直接降到了38ms大核就腾出来全力跑LightGlue效果立竿见影。不同纹理复杂度下的波动也值得记录。高纹理场景匹配点对能达到200对以上LightGlue要跑到9层耗时110ms到130ms低纹理场景比如白墙上的一个平面物体匹配点对只有30到50对LightGlue 3层就可能收敛了耗时能降到70ms以下。所以如果应用场景比较固定性能测试应该围绕实际场景来评估而不是拿一个平均数就完事。4.3 量化代价与精度权衡性能提升的背后是量化精度损失。为了验证量化对定位的影响我做了一组对比实验同一组图像分别用FP32 CPU推理和INT8 NPU推理跑SuperPoint再走相同的LightGlue和RANSAC流程统计匹配点数量和最终定位成功率。结果很直接INT8量化让SuperPoint的得分图峰值位置产生了最多2像素的偏移描述子的平均余弦相似度从0.998降到了0.987。这直接导致LightGlue匹配的正确匹配数减少了约15%最终定位框的角点误差从2像素左右增大到5像素左右定位成功率从98%降到了91%。怎么解决我的思路是混合精度而不是完全放弃量化。SuperPoint的编码器部分是量化损失的主要来源因为特征提取的精度直接决定了后续描述子的质量。但描述子头部本身输出的向量很长量化带来的相对误差其实并不大。因此可以尝试分层量化对编码器保留FP16只对描述子头做INT8量化。不过RKNN-Toolkit2的混合量化配置在当前版本还不太好用我在项目里最后采用的是折中方案SuperPoint整体用INT8量化但提高量化校准集的质量把光照变化的场景图都放进去并用余弦相似度作为校准后的验证指标强制描述子输出的余弦相似度不低于0.99。如果达不到就增加校准集图片数量或者改用FP16量化。实测在校准集质量足够好的情况下INT8量化方案的精度损失是可以接受的。4.4 压榨RK3588三核NPU与CPU协同RK3588有三颗NPU核心理论上可以把SuperPoint的三个输出分支分别放到不同核心上并行实际做的时候发现RKNN Runtime原生只支持单核调用。虽然可以通过多进程方式同时创建多个RKNN上下文来占用多个核心但SuperPoint是一个整体网络强行切分到多个NPU核心反而增加数据传输开销收益不划算。真正见效的优化是CPU和NPU流水线。我用了一个三线程结构采集线程负责取帧和预处理推理线程负责SuperPoint的NPU推理和后处理匹配线程负责LightGlue和RANSAC。关键是要让推理线程和匹配线程操作不同的帧数据避免共享锁竞争。实现上用了双缓冲队列推理线程算完一帧后把结果放入队列匹配线程从队列取上一帧结果继续处理。这样流水线起来之后端到端延迟不变但吞吐从6.4FPS提升到了7.8FPS左右因为NPU和CPU重叠工作一部分延迟被掩盖了。CPU核心绑定也做了细致调整。RK3588的4个A76大核和4个A55小核共享一个cluster但频率可以独立控制。我通过pthread_setaffinity_np把LightGlue的ONNX Runtime线程绑定到4个大核上其他任务全部放到小核和未占用的核心上。这样能避免操作系统把LightGlue线程调度到小核上导致性能骤降。绑定大核之后LightGlue的P95延迟从140ms降到了110ms这个优化几乎是免费的强烈建议做。内存复用同样重要。RKNN推理接口的输入输出如果不复用buffer每次推理都会发生内存分配。我在初始化阶段就用rknn_create_mem预分配了输入输出和中间张量的内存推理循环里只更新数据不重新分配。长期跑下来内存占用稳定在180MB左右没有明显增长。5. 常见问题与避坑指南5.1 RKNN转换踩坑记录转换过程中最折腾的是算子兼容性。复习一下我们遇到grid_sample不支持、channel shuffle性能差、L2归一化精度差这几个问题解决方案已经说过。再补充两个容易忽略的。一个是RKNN的量化数据集格式。RKNN-Toolkit2的config里quantized_dtype设成int8不需要额外写代码但量化数据集读取函数必须输出RGB顺序的图片。如果你习惯OpenCV读图直接塞进去BGR顺序会把量化统计完全搞错导致后续精度对不齐但转换过程不会报任何错误。我当时排查了很久才发现是这个问题最后在读取时统一加了一句cv2.cvtColor(img cv2.COLOR_BGR2RGB)。另一个是ONNX导出的输出顺序。RKNN模型加载后输出列表的顺序和ONNX导出的output_names顺序一致。如果代码里按照固定下标取输出一旦模型重新导出改变了输出顺序后续的定位流程会全部数据错位而且不会报错只会出错误结果。建议加载模型后打印rknn_query的输出名称和shape核对一遍再继续写业务代码。5.2 精度对不齐的排查实战模型转换完第一步要做的不是上板而是跑精度比对。把同一个输入图片分别用PyTorch CPU模型和RKNN模拟器推理对比输出的余弦相似度和最大绝对误差。这一步能过滤掉90%的转换问题。我遇到过一次很有意思的情况NPU输出的得分图和PyTorch的结果整体很接近但描述子相似度只有0.93定位成功率直接崩了。最后定位到问题是量化校准集里全是白天光照的图实际场景是傍晚光照描述子分布偏移导致量化参数不匹配。解决办法是去现场采集了50帧不同光照度的图片加入量化集重新校准后相似度恢复到0.99以上。这件事说明量化校准集不是随便找几张图凑数它必须覆盖真实应用场景的分布这是整个部署流程中最容易低估的一环。还有一个常见问题是特征点坐标偏移一个像素。原因往往是预处理插值方式不同PyTorch的resize默认用双线性插值而C侧如果用最近邻插值就会产生这个偏差。把所有预处理对齐到双线性插值就能解决不要小看这一个像素在最终定位框上会放大成好几个像素的误差。5.3 内存与长期运行稳定性板端视觉程序最怕跑几个小时之后资源耗尽。我第一版代码是每帧推理都重新创建RKNN输入输出buffer跑到第30分钟左右系统可用内存就跌到100MB以下然后开始丢帧。改成初始化时预分配并复用buffer后内存稳定在180MB跑一晚上也没有增长。另一个隐性问题是线程生命周期。LightGlue的ONNX Runtime session在线程中首次调用时会初始化线程池如果session是在主线程创建的子线程调用时存在并发初始化问题。我的做法是在匹配线程启动时先跑一次空推理预热线程池和内存池后面业务循环中的延迟更稳定这个预热也能避免运行时偶发的首个超时帧。长时间运行还需要关注NPU驱动是否有hang住的情况。我遇到过一次推理结果突然全部变成0排查后发现是之前某次NPU调用超时没做错误检查后续帧全部喂给了一个异常上下文。在业务代码里每次rknn_run返回非零值必须记录日志并重建上下文不能忽略错误码继续跑否则出问题很难复现和定位。5.4 对实际工程的建议最后是一些工程层面的建议。如果定位目标是一个平面物体单应矩阵完全够用没必要上PnP。如果要做6DoF定位必须配套相机内参标定并且在前端离线保存目标3D点。还有如果目标纹理稀疏到LightGlue匹配数量低于30对RANSAC基本解不出来稳定的单应矩阵这时候建议叠加一个低成本的ORB特征作为兜底方案用ORB的快速粗匹配筛掉无纹理帧再决定是否启用完整流程实测能节省30%无意义计算。性能上如果你的场景对帧率要求比精度高可以考虑进一步压缩输入分辨率到320x240SuperPoint的NPU耗时能降到25ms左右LightGlue的匹配耗时因为特征点更少也能大幅下降端到端大约能跑到12FPS但定位框的精度会从5像素劣化到8像素左右。这个取舍要看具体业务我们最终保留了480x640因为抓取任务需要更精确的定位结果。做完这个项目我个人最大的体会是边缘端部署从来不是把模型塞进板子就完事它是一个系统级的资源调度问题。NPU、CPU、内存、算子支持、量化分布每个环节都要通盘考虑。这个流程从最初的模型转换到最后性能优化整个过程花了差不多两周大部分时间都花在排查各种“不报错但结果错误”的隐性问题上。如果你也正在做类似的事情建议把第5节的排查清单打印出来贴在工位上能帮你省下大量重复填坑的时间。后面如果有时间我打算把LightGlue的int8量化再认真做一轮把整个流程彻底跑上NPU到时候再分享一批新的数据。