保存为NV12格式的yuv420,yyyuvuvuv
#include <string>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
int main()
{
std::string jpgpath = "test.jpg";
cv::Mat img = cv::imread(jpgpath);
int w = img.cols; /* 宽 */
int h = img.rows; /* 高 */
int imageLength = h * w * 3 / 2; /* 图像y、u、v个数总和 */
unsigned char*yuv_nv12 = new unsigned char[imageLength]; /* 存储nv12数据 */
unsigned char*yuv = new unsigned char[imageLength]; /* 存储CV_BGR2YUV_I420数据 */
cv::cvtColor(img, img, CV_BGR2YUV_IYUV); /* BGR空间转换为CV_BGR2YUV_I420 */
memcpy(yuv_nv12, img.data, imageLength*sizeof(unsigned char)); /* 此时yuv_nv12中存储的是CV_BGR2YUV_I420类型数据 */
memcpy(yuv, img.data, imageLength*sizeof(unsigned char)); /* 此时yuv中存储的是CV_BGR2YUV_I420类型数据 */
int num = 0; /* 对u、v个数的计数 */
for (int j = w * h; j != imageLength; j += 2)
{
yuv_nv12[j] = yuv[w * h + num]; /* 对yuv_nv12中u分量进行赋值 */
yuv_nv12[j + 1] = yuv[w * h + w * h / 4 + num]; /* 对yuv_nv12中v分量进行赋值 */
++num;
}
/* 保存nv12格式的yuv420 */
FILE *fp = NULL;
std::string outpath = "test.yuv";
fp = fopen(outpath.c_str(), "wb+");
if (!fp)
{
printf("file does not exist\n");
}
fwrite(yuv_nv12, 1, sizeof(char)* imageLength, fp);
fclose(fp);
fp = NULL;
/* 释放内存 */
delete[]yuv_nv12;
delete[]yuv;
yuv_nv12 = nullptr;
yuv = nullptr;
system("pause");
}
保存为CV_BGR2YUV_I420(YUV420)格式的yuv420,yyyuuuvvv
#include <string>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
int main()
{
std::string jpgpath = "test.jpg";
cv::Mat img = cv::imread(jpgpath);
cv::resize(img, img, cv::Size(img.cols/2*2,img.rows/2*2));
int w = img.cols;
int h = img.rows;
int imageLength = h * w * 3 / 2;
unsigned char*yuv = new unsigned char[imageLength];
cv::cvtColor(img, img, CV_BGR2YUV_IYUV); // CV_BGR2YUV_IYUV即I420: YYYYYYYY UU VV
memcpy(yuv, img.data, imageLength * sizeof(unsigned char));
/* 保存YUV420格式的yuv420 */
FILE *fp = NULL;
std::string outpath = "test.yuv";
errno_t ret = fopen_s(&fp, outpath.c_str(), "wb+");
if (ret)
{
printf("file does not exist\n");
}
fwrite(yuv, 1, sizeof(char)* imageLength, fp);
fclose(fp);
fp = NULL;
/* 释放内存 */
delete[]yuv;
yuv = nullptr;
system("pause");
}
反过来,将上面一段代码生成的yuv再转换为jpg图像:
#include <string>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
int main()
{
std::string yuvpath = "test.yuv";
FILE *fp = NULL;
errno_t ret = fopen_s(&fp, yuvpath.c_str(),"rb");
if (ret)
{
printf("file does not exist\n");
}
int w = 640;
int h = 512;
int imageLength = h * w * 3 / 2;
cv::Mat img_yuv = cv::Mat(h * 3 / 2, w,CV_8UC1);
fread(img_yuv.data, sizeof(unsigned char), h*w, fp);
fread(img_yuv.data+ h*w, sizeof(unsigned char), h*w/4, fp);
fread(img_yuv.data+ h*w*5/4, sizeof(unsigned char), h*w/4, fp);
fclose(fp);
fp = NULL;
cv::Mat img_bgr;
cvtColor(img_yuv, img_bgr, CV_YUV2BGR_I420); // 后缀I420代表YUV是I420格式的
cv::imwrite("img_bgr.jpg", img_bgr);
}
所用测试图像test.jpg为:

图1 test.jpg(640*512)