YYYY
YYYY
//此处是BGR图像高度
UVUV

注:YUV420sp与YUV420p的数据格式它们的UV排列在原理上是完全不同的。420p它是先把U存放完后,再存放V,也就是说UV它们是连续的。而420sp它是UV、UV这样交替存放的。
YUV420SP:

  NV12: YYYYYYYY UVUV     =>YUV420SP
  NV21: YYYYYYYY VUVU     =>YUV420SP

转换代码如下:

//BGR2YUV(YUV420SP_NV21)
void enCodeYUV420SP(unsigned  char* yuv420sp, unsigned char* rgb, int width, int height)
	if (yuv420sp == NULL || rgb == NULL)
		return;
	int frameSize = width*height;
	int yIndex = 0;
	int uvIndex = frameSize;
	int R, G, B, Y, U, V;
	for (int i = 0; i < height; i++)
		for (int j = 0; j < width; j++)
			B = rgb[(i * width + j) * 3 + 0];
			G = rgb[(i * width + j) * 3 + 1];
			R = rgb[(i * width + j) * 3 + 2];
			//RGB to YUV
			Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
			U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
			V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
			yuv420sp[yIndex++] = (unsigned char)((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
			if (i % 2 == 0 && j % 2 == 0)
				yuv420sp[uvIndex++] = (unsigned char)((V < 0) ? 0 : ((V > 255) ? 255 : V));//UV交替排列
				yuv420sp[uvIndex++] = (unsigned char)((U < 0) ? 0 : ((U > 255) ? 255 : U));
int main()
	Mat img = imread("1.jpg", 1);
	imshow("img", img);
	int height = img.rows;
	int width = img.cols;
	unsigned char* img_bgr_data = (unsigned char*)malloc(height*width * 3 * sizeof(unsigned char));
	for (int i = 0; i < height; i++)
		unsigned char* current_row = img.ptr<uchar>(i);
		for (int j = 0; j < width; j++)
			img_bgr_data[(i * width + j) * 3 + 0] = current_row[j * 3 + 0];//B
			img_bgr_data[(i * width + j) * 3 + 1] = current_row[j * 3 + 1];//G
			img_bgr_data[(i * width + j) * 3 + 2] = current_row[j * 3 + 2];//R
	//RGB->NV21(YUV420SP)
	unsigned char* img_nv21_data = (unsigned char*)malloc(height*width * 3 / 2 * sizeof(unsigned char));
	enCodeYUV420SP(img_nv21_data, img_bgr_data, width, height);
	Mat img_nv21(height * 3 / 2, width, CV_8UC1, img_nv21_data);//pointer->Mat
	// test 
	Mat img_BGR(height, width, CV_8UC3);
	cvtColor(img_nv21, img_BGR, CV_YUV2BGR_NV21);//YUV420sp->BGR
	imshow("img_BGR", img_BGR);
	return 0;

参考:http://www.cnblogs.com/azraelly/archive/2013/01/01/2841269.html
https://blog.csdn.net/u014485485/article/details/89709798

http://www.360doc.com/content/16/0517/16/496343_559909505.shtml (420p图文解释)

YUV420SP: Y数据全部从在一块,UV数据使用interleave方式存储YYYYYYYY//此处是BGR图像高度UVUV注:YUV420sp与YUV420p的数据格式它们的UV排列在原理上是完全不同的。420p它是先把U存放完后,再存放V,也就是说UV它们是连续的。而420sp它是UV、UV这样交替存放的。//BGR2YUVvoid encodeYUV420sp(unsigned char* yuv420sp, unsigned char* rgb, int wid.. void encodeYUV420sp(unsigned char* yuv420sp, unsigned char* rgb, int width, int height) if (yuv420sp == NULL || rgb == NULL) return; in...
计算机领域,RGB被称为基色分量,组合后能显示的颜色叫做颜色空间,一般取值范围从0-255(2^8,可以显示1600万多种颜色;现在有的显示器为10位位深,即2^10,约可以显示10亿种颜色) 还有一种显示方法即YUV显示法: 只黑白显示时,则只需要拿到Y值就可以了,彩色显示时则需要拿到YUV三个值。
从前文已经知道,R,G,B,3个分量都跟 亮度密切相关,也就是 3个分量里面都有大量的亮度信息。 RGB YUV 的过程实际上就是 把 RGB 3分量里面的亮度信息 提取出来,放到 Y 分量。再把 RGB 3分量里面的 色调 ,色饱和度 信息提取出来放到 U跟 V分量。 所以这是一个信息提取过程,需要经过大量的实验。 提取 Y 亮度信息的公式如下: Y = Kr * R + Kg * G + Kb * B 上面公式中的 K 是一个权重因子,Kr 代表 红色通道的权重,Kg 代表
// 假设输入图像的宽度为w,高度为h,数据存储在yuv_buffer中 // 其中,前w*h个字节是Y通道,接下来的w*h/4个字节是U通道,最后的w*h/4个字节是V通道 cv::Mat yuv_image(h + h / 2, w, CV_8UC1, yuv_buffer); cv::Mat bgr_image(h, w, CV_8UC3); cv::cvtColor(yuv_image, bgr_image, cv::COLOR_YUV2BGR_NV21); 在上面的代码中,我们首先使用cv::Mat创建一个大小为h+h/2 x w的单通道图像yuv_image,并将输入的YUV420sp字节图像数据存储到其中。然后,我们使用cv::cvtColor函数将yuv_image换为BGR格式的图像bgr_image。注意,这里使用的是COLOR_YUV2BGR_NV21参数,因为YUV420sp字节图像的存储格式通常是NV21。最后,您可以对bgr_image进行任何OpenCV支持的操作。