OpenCV – 将图片/视频转换为深度学习模型输入格式,BGR通道转RGB,图片归一化,HWC转CHW
1 将图片转换为深度模型输入格式
在C++进行人脸识别、目标检测的过程中,经常是以图片数据作为深度学习模型推理的输入数据的,但是从OpenCV读取的图片数据并不能直接用于深度学习模型的推理过程。
- 首先,OpenCV读取图片默认使用的是BGR通道排列方式,而深度学习模型一般使用RGB通道排列的方式;
- 其次,深度学习模型一般会使用归一化之后的数据格式;
- 然后,深度学习模型一般使用CHW的格式输入,C代表通道,H代表高度,W代表宽度,而OpenCV默认使用HWC的格式;
上述的一些不同需要经过正常的转换才可以将图片数据输入到深度学习模型中进行推理,如果不进行正常的转换,会导致推理的结果不正确。
1.1 自行进行转换
1.1.1 BGR通道转RGB通道
cv::Mat rgb_img;
cv::cvtColor(canvas_image, rgb_img, CV_BGR2RGB);
1.1.2 图片归一化
cv::Mat normal_img;
rgb_img.convertTo(normal_img, CV_32FC3, 1.0f / 255.0);
1.1.3 HWC转CHW
std::vector<cv::Mat> input_channels(3);
cv::split(normal_img, input_channels);
std::vector<float> result(m_Desired_Image_Width * m_Desired_Image_Height * 3);
auto data = result.data();
int channelLength = m_Desired_Image_Width * m_Desired_Image_Height;
for (int i = 0; i < 3; ++i)
{
memcpy(data, input_channels[i].data, channelLength * sizeof(float));
data += channelLength;
}
或者
cv::Mat dst;
std::vector<float> dst_data;
std::vector<cv::Mat> bgrChannels(3);
cv::split(dst, bgrChannels);
for (auto i = 0; i < bgrChannels.size(); i++)
{
std::vector<float> data = std::vector<float>(bgrChannels[i].reshape(1, 1));
dst_data.insert(dst_data.end(), data.begin(), data.end());
}
1.2 使用cv::dnn::blobFromImage对图片进行转换
OpenCV已经提供了cv::dnn::blobFromImage这个API将OpenCV的图片格式转换为深度学习网络输入数据。
cv::Mat blob = cv::dnn::blobFromImage(input_image, 1.0 / 255.0, input_image.size(), cv::Scalar(0, 0, 0), true, false, CV_32F);
该API将OpenCV图片数据进行BGR->RGB,归一化,HWC->CHW的转换,从而获得一个正确的神经网络输入数据。
1.2.1 函数形式
函数功能:从图像创建4维blob
blobFromImage(InputArray image, double scalefactor=1.0, const Size& size = Size(),
const Scalar& mean = Scalar(), bool swapRB=false, bool crop=false,int ddepth=CV_32F);
1.2.1 函数参数
- image 输入图像(具有 1、3 或 4 通道)
- size 输出图像的空间大小
- mean 这是我们要减去的均值,可以是R,G,B均值三元组,或者是一个值,每个通道都减这值。如果执行减均值,通道顺序是R、G、B。 如果,输入图像通道顺序是B、G、R,那么请确保swapRB = True,交换通道。
- scalefactor 执行完减均值后,需要缩放图像,默认是1
- swapRB 表示交换第一个和最后一个通道,OpenCV图像通道顺序是B、G、R,而减均值时顺序是R、G、B,为了解决这个矛盾,设置swapRB=True即可
- crop 如果crop裁剪为真,则调整输入图像的大小,使调整大小后的一侧等于相应的尺寸,另一侧等于或大于。然后,从中心进行裁剪。如果“裁剪”为“假”,则直接调整大小而不进行裁剪并保留纵横比。
- ddepth 输出blob的深度,选则CV_32F or CV_8U
函数返回值:函数返回具有 NCHW 尺寸顺序的4维 Mat
1.3 使用cv::dnn::blobFromImages对视频进行转换
在1.2节中演示了如何使用cv::dnn::blobFromImage
对单张图片进行转换,其实opencv也提供了对多张图片进行转换的函数cv::dnn::blobFromImages
,我们也可以使用这个函数对视频进行转换,
函数形式如下
blobFromImages(InputArrayOfArrays image, double scalefactor=1.0, const Size& size = Size(),
const Scalar& mean = Scalar(), bool swapRB=false, bool crop=false,int ddepth=CV_32F);
与函数cv::dnn::blobFromImage
相比就是第一个输入的参数不一样,我们可以使用std::vector
将单个视频的视频帧进行存储,然后作为cv::dnn::blobFromImages
的输入参数,比如
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
//#include <opencv2/blob.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
// 图片尺寸:H500,W700,C3
cv::Mat img=cv::imread("../yolov3_mini.jpg", 1);
printf("%d, %d, %d\n", img.rows, img.cols, img.channels());
// 5个batch
vector<cv::Mat> inMatList;
inMatList.push_back(img);
inMatList.push_back(img);
inMatList.push_back(img);
inMatList.push_back(img);
inMatList.push_back(img);
// ret.data 数据组织形式为nchw,数据格式为float32类型
cv::Mat ret = cv::dnn::blobFromImages(inMatList);
printf("%d, %d, %d\n", ret.rows, ret.cols, ret.channels());
// printf("%d\n", ret.rows, ret.cols, ret.channels());
// nchw
unsigned char smg[500*700*3*5];
float * data = (float * )ret.data;
for (int n=0;n<5;n++)
for (int c=0;c<3;c++)
for (int h=0;h<500;h++)
for (int w=0;w<700;w++)
{
smg[n*500*700*3+h*700*3+w*3+c] = data[n*3*500*700+c*500*700+h*700+w];
}
// 解算出原图像,验证结果
cv::imwrite("save1.bmp", cv::Mat(500 ,700, CV_8UC3, smg+700*500*3*0));
cv::imwrite("save2.bmp", cv::Mat(500 ,700, CV_8UC3, smg+700*500*3*1));
cv::imwrite("save3.bmp", cv::Mat(500 ,700, CV_8UC3, smg+700*500*3*2));
cv::imwrite("save4.bmp", cv::Mat(500 ,700, CV_8UC3, smg+700*500*3*3));
cv::imwrite("save5.bmp", cv::Mat(500 ,700, CV_8UC3, smg+700*500*3*4));
}
参考链接
本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:OpenCV – 将图片/视频转换为深度学习模型输入格式,BGR通道转RGB,图片归一化,HWC转CHW
原文链接:https://www.stubbornhuang.com/1722/
发布于:2021年09月23日 10:31:44
修改于:2023年06月26日 21:14:13
当前分类随机文章推荐
- OpenCV - 新建一个图片,并在图片上画由一点到另一点的直线,采用反走样形式 阅读3231次,点赞0次
- Python - 解决opencv-python使用cv2.imread()读取中文路径图片失败的问题 阅读2181次,点赞1次
- OpenCV - OpenCV打开摄像头显示摄像头帧率 阅读320次,点赞0次
- OpenCV - cv::VideoWriter::fourcc可支持的视频编码格式 阅读3907次,点赞0次
- OpenCV - 指定插值方法改善resize函数缩放图片时出现锯齿、失真、清晰度降低问题 阅读1351次,点赞0次
- OpenCV | OpenGL - OpenCV的cv::mat转换为OpenGL的GL_TEXTURE_2D纹理数据 阅读522次,点赞0次
- OpenCV - 打开摄像头并用窗口显示摄像头的内容 阅读3234次,点赞0次
- OpenCV - 打开视频文件,并对其中的每一帧图像进行Canny算子边缘化提取,并将结果保存为视频文件 阅读3222次,点赞0次
- Python – 解决opencv-python使用cv2.imwrite()保存中文路径图片失败的问题 阅读2298次,点赞0次
- OpenCV - 读取一个图像,并使用Canny算子进行边缘提取 阅读3286次,点赞0次
全站随机文章推荐
- WordPress - 优化Google Adsense广告js的加载速度 阅读163次,点赞0次
- 资源分享 - Mathematics for Computer Graphics , Fifth Edition 英文高清PDF下载 阅读1582次,点赞0次
- 资源分享 - 3D游戏与计算机图形学中的数学方法 第3版 , Mathematics for 3D Game Programming and Computer Graphics, Third Edition 中文版PDF下载 阅读1943次,点赞0次
- 资源分享 - 深度学习实战(杨云杜飞 清华大学出版社)高清pdf下载 阅读2736次,点赞0次
- Linux - 创建软链接、删除软链接、修改软链接 阅读47次,点赞0次
- WordPress - 修复WordPress升级5.1之后版本评论回复按钮失效不跳转以及不弹出评论框的问题 阅读1136次,点赞0次
- 资源分享 - Handbook of Discrete and Computational Geometry, Second Edition 英文高清PDF下载 阅读2362次,点赞0次
- C++ - 将一维数组/二维数组/三维数组作为函数参数传递给函数 阅读2252次,点赞0次
- 工具API推荐 - 通过QQ号获取QQ头像 阅读1670次,点赞0次
- 书籍翻译 - Fundamentals of Computer Graphics, Fourth Edition,第1章 Introduction中文翻译 阅读5823次,点赞19次
评论
169