用Linux构建嵌入式边缘AI节点:在ARM平台上轻量部署YOLO目标检测模型
ARM边缘盒跑YOLO,核心不是把.pt直接丢到板子,而是“选小模型+导ONNX+按SoC转专用引擎+INT8量化+采集/推理/后处理解耦”。纯A核可用NCNN/ONNX Runtime,带NPU的RK3588/3566走RKNN,Jetson走TensorRT,通用低功耗可TFLite,整体能把640×640检测从不可实时拉到十几到几十FPS。
一、PC端导出轻量ONNX
优先YOLOv8n/yolov5s,固定batch=1、opset 12、开simplify:
from ultralytics import YOLO
m = YOLO("yolov8n.pt")
m.export(format="onnx", imgsz=640, opset=12,
batch=1, simplify=True, dynamic=False)
simplify可删冗余算子,提升板端转换成功率。若目标平台不支持某算子,再用onnxsim处理,别在板子debug图结构。
二、按硬件转推理模型
纯ARM CPU用NCNN:
onnx2ncnn yolov8n.onnx yolov8n.param yolov8n.bin
ncnnoptimize yolov8n.param yolov8n.bin \
yolov8n-opt.param yolov8n-opt.bin 1
1表示FP16存储更省内存;多线程靠set_num_threads。 RK带NPU转RKNN并INT8:
from rknn.api import RKNN
r = RKNN()
r.config(mean_values=[[0,0,0]], std_values=[[255,255,255]],
quantized_dtype="asymmetric_quantized-u8",
target_platform="rk3588")
r.load_onnx("yolov8n.onnx")
r.build(do_quantization=True, dataset="calib_list.txt")
r.export_rknn("yolov8n.rknn"); r.release()
calib_list放100~200张真实场景图,均值/标准差/通道顺序必须和训练侧一致,否则小目标精度会掉。 Jetson用TensorRT:
trtexec --onnx=yolov8n.onnx --saveEngine=yolov8n.trt --fp16 --int8 --calibrationCacheFile=cal.cache
不支INT8先FP16,很多Orin Nano场景已经够用。
三、板端C++推理骨架(NCNN示例)
#include <ncnn/net.h>
#include <opencv2/opencv.hpp>
ncnn::Net net;
net.load_param("yolov8n-opt.param");
net.load_model("yolov8n-opt.bin");
net.opt.num_threads = 4; // 大核A72/A76可4,A53可2
cv::Mat bgr = cv::imread("cam.jpg");
ncnn::Mat in = ncnn::Mat::from_pixels_resize(
bgr.data, ncnn::Mat::PIXEL_BGR, bgr.cols, bgr.rows, 640, 640);
in.substract_mean_normalize(nullptr, new float[3]{1/255.f,1/255.f,1/255.f});
ncnn::Extractor ex = net.create_extractor();
ex.input("images", in);
ncnn::Mat out;
ex.extract("output", out); // YOLOv8 head后处理自行解码
out按[num_boxes][4+cls]解框,做置信度过滤再NMS。NCNN在ARM上INT8比FP32省约4倍体积,卷积层收益最明显。 RKNN把init_runtime挂NPU、TFLite用Interpreter加NNAPI/EdgeTPU delegate,接口不同但前后处理一致。
四、视频流水线避免卡采集
单线程读摄像头+推理会浪费NPU。用生产者-消费者:
// 采集线程写环形buffer,推理线程取最新帧
pthread_mutex_lock(&qlock);
q.push(frame); pthread_cond_signal(&qcond);
pthread_mutex_unlock(&qlock);
// 推理线程
while(run){
pthread_mutex_lock(&qlock);
while(q.empty()) pthread_cond_wait(&qcond,&qlock);
f=q.front(); q.pop(); pthread_mutex_unlock(&qlock);
infer(f); postprocess(); draw();
}
V4L2直采YUV可省OpenCV转码;RK平台用RGA做resize/色彩转换,NPU只吃预处理后的tensor,整体延迟更低。 长期运行把输入buffer、输出tensor、检测框数组全做内存池,不在循环里频繁new/delete。
五、量化与系统调优
INT8是最大提速点:RK3588上YOLOv5s 640 INT8可到8ms级,CPU XNNPACK同模型约32ms,NPU能效优势明显;精度敏感层可混合FP16。
校准集必须贴近现场,室内/户外/小目标要混合;只室内校准会导致户外置信度暴跌。
线程数不是越多越好,纯CPU按大核数设,OMP_NUM_THREADS/NCNN num_threads一起定;NPU多核用厂商core_mask。
性能模式:cpufreq设performance,NPU提频注意散热;工控长期跑加温度降频策略。
摄像头软解改硬解(RK MPP、Jetson NVDEC),显示避免cv::imshow,用DRM/Wayland或只输出JSON结果。
模型更新走A/B:新rknn/trt校验hash和单帧输出后再切,失败回退旧模型。
六、落地边界
2TOPS级NPU跑yolov8n 640做单类质检、人员/车辆计数可行;多类复杂场景、高分辨率多路视频要降imgsz到320~416或换更强NPU。纯A53无NPU不建议硬跑640全量,改用yolov5n/8n+320输入+NCNN INT8,保证5~15FPS比“大图卡顿”更实用。按“小模型+ONNX中间件+硬件专属引擎+INT8+流水线”收口,ARM Linux边缘节点可稳定承担工业摄像头、网关AI前置、现场目标告警等轻量检测任务。





