代码基本上使用的都是OpenCV的库函数 和 C++的库函数,通用性比较强,可直接拿去使用。
1.介绍
一个宽高为 w*h 的图像,如果将它保存在设备上,使用RGB编码占用的内存字节数为w*h*3,使用RGB编码占用的内存字节数为w*h*3+w*h/4+w*h/4 = w*h*3/2.
YUV有很多编码格式,YUV420就是其中一种,而NV21又是YUV420中的一种。
2.代码
代码基本上使用的都是OpenCV的库函数 和 C++的库函数,通用性比较强,可直接拿去使用。
OpenCV没有提供直接从RGB转YUV_NV21/YUV_NV21的函数,所以需要间接转
1. RGB to YUV_NV21
//YUV_I420 to YUV_NV21
void Mat_I420ToNV21(const Mat& src, Mat& _dst)
{
Mat dst(src.size(), src.type());
int w = src.cols;
int h = src.rows * 2 / 3;
memcpy(dst.data, src.data, w * h);
Mat srcU(h / 2, w / 2, CV_8U, src.data + w * h);
Mat srcV(h / 2, w / 2, CV_8U, srcU.data + srcU.cols * srcU.rows);
vector<Mat> mats;
mats.push_back(srcV); //先V
mats.push_back(srcU); //后U
Mat srcUV;
merge(mats, srcUV);
memcpy(dst.data + w * h, srcUV.data, w * h /2);
_dst = dst;
}
//RGB to YUV_NV21
void Mat_RGBToYUV_NV21(const Mat& src, Mat& dst)
{
Mat img_i420;
cvtColor(src, img_i420, COLOR_BGR2YUV_I420); //色彩空间转换,RGB先转为YUV_I420
Mat_I420ToNV21(img_i420, dst); //调用YUV_I420 to YUV_NV21
}
2. RGB to YUV_NV12
//YUV_I420 to YUV_NV12
void Mat_I420ToNV12(const Mat& src, Mat& _dst)
{
Mat dst(src.size(),src.type());
int w = src.cols;
int h = src.rows * 2 / 3;
memcpy(dst.data, src.data, w * h);
Mat srcU(h / 2, w / 2,CV_8U, src.data + w * h);
Mat srcV(h / 2, w / 2,CV_8U, srcU.data + srcU.cols * srcU.rows);
vector<Mat> mats;
mats.push_back(srcU); //先U
mats.push_back(srcV); //后V
Mat srcUV;
merge(mats, srcUV);
memcpy(dst.data + w * h, srcUV.data, w * h / 2);
_dst = dst;
}
//RGB to YUV_NV12
void Mat_RGBToYUV_NV12(const Mat& src, Mat& dst)
{
Mat img_i420;
cvtColor(src, img_i420, COLOR_BGR2YUV_I420); //色彩空间转换,RGB先转为YUV_I420
Mat_I420ToNV21(img_i420, dst); //调用YUV_I420 to YUV_NV12
}
3. 用法
//1.RGB转YUV_NV21,直接调用下面函数
Mat_RGBToYUV_NV21(RGB_img, YUV_img);
//2.RGB转YUV_NV12,直接调用下面函数
Mat_RGBToYUV_NV12(RGB_img, YUV_img);
4. YUV_I420转RGB,直接用OpenCV提供的函数
cvtColor(srcYUV, RGB_img, COLOR_YUV2RGB_I420)
5. YUV_NV12/YUV_NV21转RGB,直接用OpenCV提供的函数
cvtColor(srcYUV, RGB_img, COLOR_YUV2RGB_NV12);
cvtColor(srcYUV, RGB_img, COLOR_YUV2RGB_NV21);