在OpenCV的dnn模块中,cv::dnn::blobFromImage
是一个非常重要的预处理函数,用于将输入图像转换为深度学习模型(神经网络)可接受的 blob格式,是连接原始图像与模型输入的关键步骤。其核心作用是对图像进行标准化、尺寸调整、通道转换等预处理操作,使其符合目标网络的输入要求。
一、函数作用
深度学习模型的输入通常需要特定的格式(如固定尺寸、通道顺序、数值范围等),而原始图像(如OpenCV读取的Mat
)往往不符合这些要求。blobFromImage
的主要功能是:
- 调整图像尺寸至模型要求的输入大小;
- 对像素值进行缩放(如归一化到[0,1]);
- 减去均值(消除光照等干扰);
- 转换通道顺序(如BGR→RGB,适应模型需求);
- 最终输出一个4维的“blob”数组,作为模型的输入。
二、函数原型
void cv::dnn::blobFromImage(
InputArray src, // 输入图像(单张图像,如cv::Mat)
OutputArray blob, // 输出的blob(4维数组,符合模型输入格式)
double scalefactor = 1.0, // 缩放因子:对图像像素值的缩放比例
Size size = Size(), // 目标尺寸:模型要求的输入宽高 (W, H)
const Scalar& mean = Scalar(),// 均值:需要从图像中减去的均值(B, G, R顺序,与OpenCV一致)
bool swapRB = false, // 是否交换红蓝通道(BGR→RGB)
bool crop = false, // 是否裁剪:调整尺寸时是否保持比例并裁剪(而非拉伸)
int ddepth = CV_32F // 输出blob的数据类型(通常为CV_32F或CV_8U)
);
三、参数详细解释
1. InputArray src
输入的原始图像,通常是cv::Mat
类型(单通道灰度图或三通道彩色图)。图像的像素值范围一般为[0, 255]
(CV_8U
类型)。
2. OutputArray blob
输出的blob(4维数组),格式为 [1, C, H, W]
:
1
:批量大小(batch size),因输入是单张图像,故为1;C
:通道数(如RGB/BGR为3,灰度图为1);H
/W
:图像的高度和宽度(由size
参数指定)。
blob的数据类型由ddepth
决定(默认CV_32F
)。
3. double scalefactor
像素值的缩放因子。作用是将图像像素值缩放到模型要求的范围(如[0,1]
或[-1,1]
)。
- 若模型要求像素值归一化到
[0,1]
,可设为1.0 / 255.0
(将[0,255]
缩放到[0,1]
); - 若模型不需要额外缩放(仅减去均值),可设为
1.0
。
4. Size size
模型要求的输入尺寸 (W, H)
(宽,高)。例如,YOLOv5的输入尺寸可能为(640, 640)
,MobileNet可能为(224, 224)
。
5. const Scalar& mean
需要从图像中减去的均值(用于消除光照影响),格式为Scalar(b, g, r)
(与OpenCV的BGR通道顺序一致)。
- 若模型需要减去像素均值(如
[104, 117, 123]
,常见于VGG等网络),直接传入该值; - 若模型不需要减均值(仅归一化),设为
Scalar(0,0,0)
即可。
6. bool swapRB
是否交换红(R)和蓝(B)通道。
- OpenCV读取的彩色图像默认是 BGR 通道顺序;
- 但多数深度学习模型(如TensorFlow、PyTorch训练的模型)要求输入为 RGB 顺序。因此,实际使用中通常需设为
true
(将BGR转为RGB)。
7. bool crop
调整图像尺寸时是否裁剪(而非拉伸),用于保持图像比例:
crop = true
:
先将图像按比例缩放到“刚好覆盖size
”(即缩放后图像的宽或高等于size
的宽或高,另一维度更大),再从中心裁剪到size
大小(避免变形)。crop = false
:
直接将图像拉伸/压缩到size
大小(可能导致比例失调,适合对比例不敏感的场景)。
8. int ddepth
输出blob的数据类型,默认CV_32F
(32位浮点数)。多数深度学习模型的输入为float32,故无需修改;若需整数类型,可设为CV_8U
。
四、处理流程(内部逻辑)
blobFromImage
的核心是对图像进行一系列预处理,步骤如下:
- 调整尺寸:根据
size
和crop
参数,将输入图像调整为目标宽高(保持比例裁剪或直接拉伸); - 通道转换:若
swapRB = true
,将BGR转为RGB; - 减去均值:从每个通道的像素值中减去
mean
对应通道的均值(如B通道减mean[0]
,G通道减mean[1]
,R通道减mean[2]
); - 缩放像素:将像素值乘以
scalefactor
(如归一化到[0,1]
); - 格式转换:将处理后的图像转换为4维blob(
[1, C, H, W]
),并设置为ddepth
指定的数据类型。
五、示例代码
以“YOLOv5模型预处理”为例(YOLOv5要求输入为(640,640)
,RGB通道,像素值归一化到[0,1]
,无需减均值):
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
using namespace cv;
using namespace cv::dnn;
int main() {
// 读取图像(OpenCV默认BGR格式)
Mat img = imread("test.jpg");
if (img.empty()) {
printf("无法读取图像!");
return -1;
}
// 定义模型输入参数
Size targetSize(640, 640); // YOLOv5输入尺寸 (W=640, H=640)
double scalefactor = 1.0 / 255.0; // 归一化到[0,1]
Scalar mean(0, 0, 0); // 不减均值
bool swapRB = true; // BGR→RGB(YOLOv5需要RGB)
bool crop = true; // 保持比例裁剪
// 生成blob
Mat blob;
blobFromImage(img, blob, scalefactor, targetSize, mean, swapRB, crop);
// 此时blob格式为 [1, 3, 640, 640],可直接输入YOLOv5模型
return 0;
}
六、注意事项
- 通道顺序:OpenCV默认BGR,模型若需RGB,务必设
swapRB = true
; - 均值与缩放:若需同时归一化(如
[0,255]→[0,1]
)和减均值,需注意顺序:先减均值再缩放,还是先缩放再减均值?blobFromImage
内部是 先减均值,再乘以scalefactor。因此,若均值是基于[0,255]
的(如[104,117,123]
),需先减均值,再缩放(此时scalefactor=1.0
);若均值是基于[0,1]
的,需先缩放(scalefactor=1/255
),再减均值(如mean=(0.485, 0.456, 0.406)
)。
- 裁剪与拉伸:对比例敏感的模型(如分类模型)建议
crop = true
;对比例不敏感的模型(如目标检测)可设crop = false
(或按模型要求)。
通过cv::dnn::blobFromImage
,可以快速将原始图像转换为符合深度学习模型输入要求的格式,是OpenCV中进行模型推理前预处理的核心函数。