YUV12(420) (from)to RGB24

Posted cynchanpin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了YUV12(420) (from)to RGB24相关的知识,希望对你有一定的参考价值。

直接上代码


#include <opencv2/opencv.hpp>
#include <stdio.h>

#define  min(a,b)  ((a<b)?a:b)
#define  max(a,b)  ((a>b)?a:b)
	/************************************************************************/
	/*                     YUV12 to RGB24   (4)	Basic Optimizations	 3.1	*/
	/************************************************************************/
	int  yuv420_to_argb888(const unsigned char *y, const unsigned char *u,const unsigned char *v ,int width ,int height ,unsigned char *rgb)
	{
		static const int Precision = 32768 ;
		static const int Coefficient_y =  (int) (1.164*Precision + 0.5);
		static const int Coefficient_rv = (int) (1.596*Precision + 0.5);
		static const int Coefficient_gu = (int) (0.391*Precision + 0.5);
		static const int Coefficient_gv = (int) (0.813*Precision + 0.5);
		static const int Coefficient_bu = (int) (2.018*Precision + 0.5);
		static  int CoefficientY[256];
		static  int CoefficientRV[256];
		static  int CoefficientGU[256];
		static  int CoefficientGV[256];
		static  int CoefficientBU[256];
		static  int _CoefficientsR[1024];
		//static   int _CoefficientsG[1024];
		//static   int _CoefficientsB[1024];
		static int flag = 1 ;

		if (flag)
		{

			for(int i =0;i<256;i++)
			{
				CoefficientY[i] = Coefficient_y *(i - 16) + (Precision/2);
				CoefficientGV[i] = -Coefficient_gv *(i - 128);
				CoefficientBU[i] = Coefficient_bu *(i - 128);
				CoefficientGU[i] = -Coefficient_gu *(i - 128);
				CoefficientRV[i] = Coefficient_rv *(i - 128);
			}

			for(int j=0;j<1024;j++)
			{
				_CoefficientsR[j] = min((max(j-320,0)),255) ;
				//_CoefficientsG[j] = min((max(j-320,0)),255) ;
				//_CoefficientsB[j] = min((max(j-320,0)),255) ;
			}

			flag = 0;
		}
		CoefficientY[0] = -593888;
		CoefficientY[1] = -555746;                            //修复bug!! CoefficientY[1]在第二次进入此函数的时候意外被改动为非常大的数,理论值应该为-555746
		int *CoefficientsR = &_CoefficientsR[320];
		// int *CoefficientsG = &_CoefficientsG[320];
		// int *CoefficientsB = &_CoefficientsB[320];

		for ( int h=0;h<height;h++)
		{

				for (int w=0;w<width;w++)
				{
					int k = h*width + w;
					int index = k*3;
					int i = (h/2)*(width/2)+(w/2);
					int Y = y[k];
					int U = u[i];
					int V = v[i];

					
					//3.3 Optimizations Removing Conditional Tests
					int r = CoefficientY[Y] + CoefficientRV[V];
					int g = CoefficientY[Y] + CoefficientGU[U]+ CoefficientGV[V];
					int b = CoefficientY[Y] + CoefficientBU[U];
					rgb[index]   = CoefficientsR[r/Precision];
					rgb[index+1] = CoefficientsR[g/Precision];
					rgb[index+2] = CoefficientsR[b/Precision];
								
				}
		}
		return 0;
	}
//Compare 3 images histograms together, 
// the first is divided in half along y to test its other half
// Call is: 
//    ch7HistCmp modelImage0 testImage1 testImage2 badImage3
// Note that the model image is split in half.  Top half(0) makes model.  It‘s then tested
// against its lower half(0), testImages 1 and 2 in different lighting and different object 3
// 
int main( int argc, char** argv ) {

    IplImage* src[5], *tmp;
	int i;
		if((src[0] = cvLoadImage(argv[1], 1)) == 0){ //We‘re going to split this one in half
			printf("Error on reading image 1, %s\n",argv[1]);
			return(-1);
		}
		//Parse the first image into two image halves divided halfway on y
		printf("Getting size [[%d] [%d]]  format is [%s]\n",src[0]->width,src[0]->height,src[0]->channelSeq);
		CvSize size = cvGetSize(src[0]);
		printf("Get size %d %d\n",size.width,size.height);
		int width = size.width;
		int height = size.height;
		int halfheight = height >> 1;
                //RGB888 to YUV420
		unsigned char * rgb = (unsigned char*)src[0]->imageData;
		unsigned char * yuv = (unsigned char*)malloc(width*height + width*height/2);
		unsigned char * y = yuv;
		unsigned char * u = &yuv[width*height];
		unsigned char * v = &yuv[width*height+width*height/4];

		int k = 0;
		for(int i = 0;i<height ;i++)
		{
			for(int j =0;j<width;j++)
			{
				int index = i*width+j;
				unsigned char R = 	rgb[width*i*3+j*3];
				unsigned char G = 	rgb[width*i*3+j*3+1];
				unsigned char B = 	rgb[width*i*3+j*3+2];
				y[index] =  ( (  66 * R + 129 * G +  25 * B + 128) >> 8) +  16;
				y[index] =  min(max(y[index],0),255);

				if( (j%2 ==0)&&(i%2 == 0) )
				{
					k++;
					u[k] =  ( ( -38 * R -  74 * G + 112 * B + 128) >> 8) + 128;
					v[k] =  ( ( 112 * R -  94 * G -  18 * B + 128) >> 8) + 128;
					u[k] =  min(max(u[k],0),255);
					v[k] =  min(max(v[k],0),255);
				}
			}
		}


		src[1] = cvCreateImage(cvSize(width,height), 8, 3);
		yuv420_to_argb888((const unsigned char*)y,(const unsigned char*)u,(const unsigned char*)v,width,height,(unsigned char *)src[1]->imageData);
		
        //DISPLAY
	cvNamedWindow( "Source0", 1 );
        cvShowImage(   "Source0", src[0] );//原图RGB
	cvNamedWindow( "Source1", 1 );
        cvShowImage(   "Source1", src[1] );//经过RGB88->YUV420->RGB888后的图像

        cvWaitKey(0);
        free(yuv)  }





參考:https://msdn.microsoft.com/en-us/library/aa917087.aspx

以上是关于YUV12(420) (from)to RGB24的主要内容,如果未能解决你的问题,请参考以下文章

C++ YUV420文件读取与显示,绘制矩形框,绘制线段(绘制直线),绘制多边形(常用YUV数据格式——YUV420P中的YU12与YUV420SP中的NV21)

C++ YUV420文件读取与显示,绘制矩形框,绘制线段(绘制直线),绘制多边形(常用YUV数据格式——YUV420P中的YU12与YUV420SP中的NV21)

YUV模型:YUV420P和YUV420SP

详解 YUV 格式(I420/YUV420/NV12/NV12/YUV422)

视频存储格式YUV420 NV12 NV21 i420 YV12

YUV存储格式:YU12_I420_YV12_NV12_NV21