2、图像基础:RGB、BGR、灰度、YUV等常见图像格式及其在RKNN中的表示

在RKNN模型部署中,图像格式的选择直接决定了预处理流水线的复杂度、内存带宽占用以及最终推理精度。许多开发者习惯使用OpenCV读取图像后直接送入模型,但在RKNN工具链中,输入张量的通道顺序、数据排布(Layout)和归一化方式必须与模型训练时完全一致,否则会出现“模型在PC上精度正常,部署到NPU后精度骤降”的典型问题。本节将系统梳理RGB、BGR、灰度、YUV等常见图像格式的本质差异,并重点说明它们在RKNN中的张量表示规则。

RKNN图像格式与张量表示链路 输入源 摄像头/图片/视频帧 OpenCV/解码器输出 格式转换 BGR→RGB / RGB→BGR YUV→RGB / 灰度→RGB 数据排布 NHWC / NCHW 通道维度的位置 归一化 /255 或 (x-mean)/std RKNN 输入张量表示 shape = [1, H, W, C] 或 [1, C, H, W] dtype = uint8 / float16 / float32 常见格式对比 RGB:3通道,颜色敏感 BGR:OpenCV默认,通道反转 灰度:单通道,亮度信息 YUV:亮度+色度,视频常用 RKNN关键要点 • 需与训练时格式一致 • 支持NHWC/NCHW • 归一化参数需匹配 • 灰度图需扩展通道 常见错误 ✗ 通道顺序不匹配 ✗ Layout设置错误 ✗ 归一化参数不一致 ✗ 灰度图未扩展通道

2.1 核心原理:图像格式的本质与存储差异

图像在计算机中的本质是多维数组,不同格式只是对“颜色信息如何编码”的不同约定。理解这一点是掌握RKNN输入处理的前提。

  • RGB格式:每个像素由红(R)、绿(G)、蓝(B)三个通道组成,每个通道通常占8bit(0-255)。RGB是显示器、相机传感器和大多数深度学习模型训练时的标准格式。在内存中,RGB图像通常按“像素连续存储”的方式排列,即第一个像素的R、G、B值紧挨着存放。
  • BGR格式:与RGB的唯一区别是通道顺序反转。OpenCV的cv2.imread()默认返回BGR格式,而PyTorch、TensorFlow等框架在训练时通常使用RGB。如果直接将OpenCV读取的图像送入RKNN,模型看到的通道顺序与训练时相反,导致精度严重下降。
  • 灰度图:只有一个通道,取值范围0-255,表示亮度信息。灰度图不包含颜色信息,常用于边缘检测、人脸关键点等任务。在RKNN中,灰度图需要被扩展为3通道(通常将单通道复制3次)才能匹配模型的输入要求。
  • YUV格式:将亮度(Y)与色度(U、V)分离,Y分量表示灰度信息,U、V分量表示颜色差异。YUV是视频编码和摄像头输出的主流格式(如YUV420、YUV422),因为人眼对亮度更敏感,可以压缩色度采样率来节省带宽。RKNN的NPU通常支持直接输入YUV数据,但需要正确配置格式转换参数。
关键认知:RKNN本身不关心图像是“什么格式”,它只关心输入张量的数值排列。格式转换必须在送入NPU之前完成,或者通过RKNN的config中的reorder_channel参数让NPU硬件完成通道重排。

2.2 判断方法:如何确定RKNN输入张量的正确表示

在编写RKNN推理代码之前,必须明确以下三个关键参数。错误的判断会导致推理结果完全不可用。

  1. 查看模型训练时的输入格式:从模型导出文件(如ONNX、PyTorch)中查看输入节点的shape和dtype。ONNX模型可以使用onnx.shape_inference工具,PyTorch模型直接查看forward()函数的输入定义。
  2. 确认训练时的通道顺序:如果训练代码使用transforms.ToTensor()(PyTorch),则输入为RGB;如果使用OpenCV读取后直接训练,则输入为BGR。查看训练脚本中的数据加载部分即可确认。
  3. 确定Layout(数据排布):RKNN支持NHWC(通道在最后)和NCHW(通道在第二维)两种布局。TensorFlow模型通常使用NHWC,PyTorch模型通常使用NCHW。在RKNN的config中通过layout参数指定。
模型来源 默认通道顺序 默认Layout RKNN配置建议
PyTorch (torchvision) RGB NCHW layout='NCHW', reorder_channel='0 1 2'
TensorFlow/Keras RGB NHWC layout='NHWC', reorder_channel='0 1 2'
OpenCV训练 BGR NHWC layout='NHWC', reorder_channel='2 1 0'
Caffe BGR NCHW layout='NCHW', reorder_channel='2 1 0'

2.3 案例拆解:YUV摄像头输入在RKNN上的完整处理流程

以RK3588平台接入USB摄像头(输出YUV422格式)为例,展示从原始帧到RKNN输入张量的完整转换链路。该案例是实际项目中常见的工程场景。

背景与约束:摄像头输出YUV422格式,分辨率1920×1080,帧率30fps。目标模型为YOLOv5s(PyTorch训练,RGB输入,NCHW布局,输入尺寸640×640)。系统内存带宽有限,需要最小化CPU拷贝次数。

初始现象:直接使用cv2.VideoCapture读取摄像头帧,然后调用RKNN推理,发现检测框位置偏移严重,置信度普遍低于0.3。

分析判断过程:

  1. 检查cv2.VideoCapture返回的帧格式:OpenCV会自动将YUV转换为BGR,因此frame是BGR格式。
  2. YOLOv5训练时使用RGB输入,因此BGR→RGB转换是必须的。
  3. YOLOv5的PyTorch模型输入为NCHW布局,而RKNN默认可能使用NHWC,需要显式指定。
  4. 归一化参数:YOLOv5使用/255归一化,RKNN的quantized_dtype需要匹配。

实际操作步骤:

# RKNN配置
rknn.config(
    mean_values=[[0, 0, 0]],
    std_values=[[255, 255, 255]],
    target_platform='rk3588',
    reorder_channel='2 1 0',  # BGR→RGB
    layout='NCHW'             # 匹配PyTorch
)

# 推理时预处理
frame = cv2.VideoCapture(0).read()[1]  # BGR, 1920x1080
img = cv2.resize(frame, (640, 640))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 显式转换
# 或者依赖reorder_channel,但显式转换更清晰

# 送入RKNN
outputs = rknn.inference(inputs=[img])

结果对比:修正后检测置信度恢复到0.7以上,框位置准确。CPU占用率从85%降至40%,因为避免了不必要的格式转换拷贝。

风险与代价:如果摄像头直接输出YUV,可以跳过OpenCV的BGR转换,直接使用rknn.inference(inputs=[yuv_frame])并配置input_format='yuv422',但需要确保YUV的采样格式(如YUYV、UYVY)与NPU硬件匹配。此方案可进一步降低延迟,但调试复杂度更高。

经验总结:在RKNN项目中,“显式转换优于隐式依赖”。虽然RKNN提供了reorder_channel和layout参数,但在代码中显式进行cv2.cvtColor和np.transpose可以让问题更容易定位,也便于在不同硬件平台间移植。

2.4 常见误区与总结复盘

以下是RKNN图像格式处理中最容易踩的坑,每个都对应着实际项目中的血泪教训。

  • 误区一:认为OpenCV读取的图像可以直接送入RKNN。OpenCV默认BGR,而大多数模型训练使用RGB。即使模型是BGR训练,也必须确认reorder_channel设置正确。
  • 误区二:忽略Layout差异。PyTorch模型导出为ONNX后,输入Layout可能是NCHW,但RKNN的C接口默认使用NHWC。如果layout配置错误,图像会“扭曲”但不会报错,排查难度极大。
  • 误区三:灰度图直接作为单通道输入。大多数模型(包括MobileNet、ResNet)的输入层是3通道。灰度图必须通过np.repeat或cv2.cvtColor扩展为3通道,否则维度不匹配。
  • 误区四:归一化参数随意设置。RKNN的mean_values和std_values必须与训练时完全一致。例如YOLOv5使用mean=0, std=255,而某些模型使用mean=[0.485,0.456,0.406], std=[0.229,0.224,0.225](ImageNet标准化)。错误设置会导致精度下降,但不会报错。
  • 误区五:YUV格式直接送入RKNN而不考虑采样格式。YUV420和YUV422的U、V分量排列不同,NPU硬件只支持特定格式。必须查阅RKNN SDK文档确认支持的YUV变体。
风险提示:当推理结果异常时,请按以下顺序排查:① 检查通道顺序(BGR/RGB);② 检查Layout(NHWC/NCHW);③ 检查归一化参数;④ 检查图像尺寸是否与模型输入一致;⑤ 检查dtype是否为uint8或float32。90%的RKNN精度问题都出在这五个环节。

总结:图像格式在RKNN中的表示本质上是“将外部图像数据映射到模型期望的张量空间”。掌握RGB/BGR/灰度/YUV的存储差异,理解NHWC与NCHW的维度含义,并严格对齐归一化参数,是确保NPU推理精度与训练一致的关键。建议在项目初期就建立一张“输入格式对照表”,记录模型来源、通道顺序、Layout、归一化参数,避免后期反复调试。