YOLO26N 姿态估计 RKNN 部署:RK3588 NPU 实战 1. RKNN 转换 #!/usr/bin/env python3 """onnx_to_rknn_pose.py""" from rknn. apiimport RKNNdef convert ( onnx_path, rknn_path, calib_list) : rknn= RKNN( verbose= True ) rknn. config( mean_values= [ [ 0 , 0 , 0 ] ] , std_values= [ [ 255 , 255 , 255 ] ] , target_platform= 'rk3588' , quantized_dtype= 'asymmetric_quantized-8' , ) ret= rknn. load_onnx( model= onnx_path) assert ret== 0 , "加载 ONNX 失败" ret= rknn. build( do_quantization= True , dataset= calib_list, ) assert ret== 0 , "构建失败" ret= rknn. export_rknn( rknn_path) assert ret== 0 , "导出失败" print ( f"✅ RKNN 已导出: { rknn_path} " ) rknn. release( ) if __name__== "__main__" : convert( "yolo26n-pose.onnx" , "yolo26n-pose.rknn" , "calibration_list.txt" ) 2. RKNN 推理 #!/usr/bin/env python3 """rknn_pose.py - RK3588 姿态估计""" from rknnlite. apiimport RKNNLiteimport cv2import numpyas np SKELETON= [ ( 0 , 1 ) , ( 0 , 2 ) , ( 1 , 3 ) , ( 2 , 4 ) , ( 5 , 6 ) , ( 5 , 7 ) , ( 6 , 8 ) , ( 7 , 9 ) , ( 8 , 10 ) , ( 11 , 12 ) , ( 11 , 13 ) , ( 12 , 14 ) , ( 13 , 15 ) , ( 14 , 16 ) , ( 5 , 11 ) , ( 6 , 12 ) , ] class RKNNPoseDetector : def __init__ ( self, rknn_path, conf_thresh= 0.3 ) : self. rknn= RKNNLite( ) self. rknn. load_rknn( rknn_path) self. rknn. init_runtime( core_mask= RKNNLite. NPU_CORE_0_1_2) self. conf_thresh= conf_threshdef detect ( self, image) : img= cv2. resize( image, ( 640 , 640 ) ) img= cv2. cvtColor( img, cv2. COLOR_BGR2RGB) outputs= self. rknn. inference( inputs= [ img] ) predictions= outputs[ 0 ] [ 0 ] . T# [8400, 56] scores= predictions[ : , 4 ] mask= scores> self. conf_thresh boxes= predictions[ mask, : 4 ] scores= scores[ mask] kpts= predictions[ mask, 6 : ] . reshape( - 1 , 17 , 3 ) return boxes, scores, kptsdef draw ( self, image, boxes, scores, kpts) : h, w= image. shape[ : 2 ] sx, sy= w/ 640 , h/ 640 for iin range ( len ( boxes) ) : for ( a, b) in SKELETON: if kpts[ i] [ a] [ 2 ] > 0.3 and kpts[ i] [ b] [ 2 ] > 0.3 : pt1= ( int ( kpts[ i] [ a] [ 0 ] * sx) , int ( kpts[ i] [ a] [ 1 ] * sy) ) pt2= ( int ( kpts[ i] [ b] [ 0 ] * sx) , int ( kpts[ i] [ b] [ 1 ] * sy) ) cv2. line( image, pt1, pt2, ( 0 , 255 , 0 ) , 2 ) for ( x, y, vis) in kpts[ i] : if vis> 0.3 : cv2. circle( image, ( int ( x* sx) , int ( y* sy) ) , 3 , ( 0 , 0 , 255 ) , - 1 ) return imageif __name__== "__main__" : model= RKNNPoseDetector( "yolo26n-pose.rknn" ) image= cv2. imread( "test.jpg" ) boxes, scores, kpts= model. detect( image) result= model. draw( image, boxes, scores, kpts) cv2. imwrite( "result.jpg" , result) print ( f"检测到 { len ( boxes) } 个人" ) 3. RK3588 性能 RK3588 NPU 性能(YOLO26N-Pose, 640x640, INT8): ┌──────────────────┬──────────┐ │ 指标 │ 数值 │ ├──────────────────┼──────────┤ │ 推理延迟 │ 12ms │ │ FPS │ 83 │ │ 功耗 │ 5W │ │ NPU 核心 │ 3 核并行 │ │ 模型大小 │ 3.2MB │ └──────────────────┴──────────┘4. RKNN 优化技巧 RKNN 优化清单: ├── 量化 │ ├── 使用 200+ 张校准图片 │ ├── 校准图片覆盖全场景 │ └── 验证量化精度损失 <2 mAP ├── NPU 核心 │ ├── 使用 3 核并行(CORE_0_1_2) │ ├── 避免单核瓶颈 │ └── 监控 NPU 利用率 ├── 内存 │ ├── 减少 CPU-NPU 数据拷贝 │ ├── 使用零拷贝接口 │ └── 预分配输出缓冲区 └── 流水线 ├── 采集/推理/后处理并行 ├── 使用双缓冲 └── 减少空闲时间总结 平台 延迟 FPS 功耗 适用场景 RK3588 NPU 12ms 83 5W 低功耗边缘 Jetson Orin NX 5.2ms 192 15W 高性能边缘 RTX 4090 1.5ms 667 450W 服务器