YUV420P轉換為RGB32格式

masikkk發表於2013-08-16

從網路攝像機中獲取的幀資料是YUV420P格式的,而我們處理影象需要RGB格式,在網上找了一段將YUV420P格式的幀轉換為RGB的程式碼。


<方法一> 直接計算,效率低

// 轉換 YV12 到 RGB24
// pYUV 的大小 (3 * iWidth * iHeight / 2)
// pRGB 的大小 (3 * iWidth * iHeight)
// 如果成功返回 true, 否則 false
bool YV12_to_RGB24(unsigned char* pYV12, unsigned char* pRGB24, int iWidth, int iHeight)
{
if(!pYV12 || !pRGB24)
return false;

const long nYLen = long(iHeight * iWidth);
const int nHfWidth = (iWidth>>1);

if(nYLen<1 || nHfWidth<1) 
return false;

// yv12資料格式,其中Y分量長度為width * height, U和V分量長度都為width * height / 4
// |WIDTH |
// y......y--------
// y......y HEIGHT
// y......y
// y......y--------
// v..v
// v..v
// u..u
// u..u
unsigned char* yData = pYV12;
unsigned char* vData = &yData[nYLen];
unsigned char* uData = &vData[nYLen>>2];

if(!uData || !vData)
return false;

// Convert YV12 to RGB24
// 
// formula
// [1 1 1 ]
// [r g b] = [y u-128 v-128] [0 0.34375 0 ]
// [1.375 0.703125 1.734375]
// another formula
// [1 1 1 ]
// [r g b] = [y u-128 v-128] [0 0.698001 0 ]
// [1.370705 0.703125 1.732446]
int rgb[3];
int i, j, m, n, x, y;
m = -iWidth;
n = -nHfWidth;
for(y=0; y < iHeight; y++)
{
m += iWidth;
if(!(y % 2))
n += nHfWidth;
for(x=0; x < iWidth; x++)
{
i = m + x;
j = n + (x>>1);
rgb[2] = int(yData[i] + 1.370705 * (vData[j] - 128)); // r分量值
rgb[1] = int(yData[i] - 0.698001 * (uData[j] - 128) - 0.703125 * (vData[j] - 128)); // g分量值
rgb[0] = int(yData[i] + 1.732446 * (uData[j] - 128)); // b分量值

j = nYLen - iWidth - m + x;
i = (j<<1) + j;
for(j=0; j<3; j++)
{
if(rgb[j]>=0 && rgb[j]<=255)
pRGB24[i + j] = rgb[j];
else
pRGB24[i + j] = (rgb[j] < 0) ? 0 : 255;
}
}
}
return true;
}

在利用OpenCV進行處理時,如果直接將轉換好的資料賦給IplImage->imageData,會出現紅藍通道對調的情況,因為OpenCV中預設使用的是BGR的排列方式。

將程式碼中的給rgb複製的一段稍微改一下就行,改為:

rgb[0] = int(yData[i] + 1.370705 * (vData[j] - 128)); // r分量值
rgb[1] = int(yData[i] - 0.698001 * (uData[j] - 128) - 0.703125 * (vData[j] - 128)); // g分量值
rgb[2] = int(yData[i] + 1.732446 * (uData[j] - 128)); // b分量值


<方法二>查表,效率高

#include   <string> 
#include   <string.h> 
using   namespace   std; 

static   long   int   crv_tab[256]; 
static   long   int   cbu_tab[256]; 
static   long   int   cgu_tab[256]; 
static   long   int   cgv_tab[256]; 
static   long   int   tab_76309[256]; 
static   unsigned   char   clp[1024]; //for   clip   in   CCIR601 


void   InitConvtTbl(); 
void   YUV2RGB420(unsigned   char   *src,   unsigned   char   *dst_ori, 
	int   width,int   height); 

/****************************************************/ 
/* Sum   the   input */ 
/* Input:   input,   len */ 
/* Output:   input */ 
/* Algorithm:   add */ 
/****************************************************/ 
void   InitConvtTbl() 
{ 
	long   int   crv,cbu,cgu,cgv; 
	int   i,ind;       

	crv   =   104597;   cbu   =   132201;     /*   fra   matrise   i   global.h   */ 
	cgu   =   25675;     cgv   =   53279; 

	for   (i   =   0;   i   <   256;   i++)   { 
		crv_tab[i]   =   (i-128)   *   crv; 
		cbu_tab[i]   =   (i-128)   *   cbu; 
		cgu_tab[i]   =   (i-128)   *   cgu; 
		cgv_tab[i]   =   (i-128)   *   cgv; 
		tab_76309[i]   =   76309*(i-16); 
	} 

	for   (i=0;   i <384;   i++) 
		clp[i]   =0; 
	ind=384; 
	for   (i=0;i <256;   i++) 
		clp[ind++]=i; 
	ind=640; 
	for   (i=0;i <384;i++) 
		clp[ind++]=255; 
}

void   YUV2RGB420(unsigned   char   *src,   unsigned   char   *dst_ori, 
	int   width,int   height) 
{ 
	unsigned   char   *src0; 
	unsigned   char   *src1; 
	unsigned   char   *src2; 
	int   y1,y2,u,v;   
	unsigned   char   *py1,*py2; 
	int   i,j,   c1,   c2,   c3,   c4; 
	unsigned   char   *d1,   *d2,   *d3; 

	//Initialization 
	src0=src; 
	src1=src+width*height; 
	src2=src+width*height+width*height/4; 

	py1=src0; 
	py2=py1+width; 
	d1=dst_ori + 3 * width * (height -1); 
	d2=d1-3*width; 
	for   (j   =   0;   j   <   height;   j   +=   2)   {   
		for   (i   =   0;   i   <   width;   i   +=   2)   { 

			u   =   *src1++; 
			v   =   *src2++; 

			c1   =   crv_tab[v]; 
			c2   =   cgu_tab[u]; 
			c3   =   cgv_tab[v]; 
			c4   =   cbu_tab[u]; 

			//up-left 
			y1   =   tab_76309[*py1++]; 
			*d1++   =   clp[384+((y1   +   c4)>> 16)];     
			*d1++   =   clp[384+((y1   -   c2   -   c3)>> 16)]; 
			*d1++   =   clp[384+((y1   +   c1)>> 16)]; 

			//down-left 
			y2   =   tab_76309[*py2++]; 
			*d2++   =   clp[384+((y2   +   c4)>> 16)];     
			*d2++   =   clp[384+((y2   -   c2   -   c3)>> 16)]; 
			*d2++   =   clp[384+((y2   +   c1)>> 16)]; 

			//up-right 
			y1   =   tab_76309[*py1++]; 
			*d1++   =   clp[384+((y1   +   c4)>> 16)];     
			*d1++   =   clp[384+((y1   -   c2   -   c3)>> 16)]; 
			*d1++   =   clp[384+((y1   +   c1)>> 16)]; 

			//down-right 
			y2   =   tab_76309[*py2++]; 
			*d2++   =   clp[384+((y2   +   c4)>> 16)];     
			*d2++   =   clp[384+((y2   -   c2   -   c3)>> 16)]; 
			*d2++   =   clp[384+((y2   +   c1)>> 16)]; 
		} 
		d1   -=   3*width * 3; 
		d2   -=   3*width * 3; 
		py1+=       width; 
		py2+=       width; 
	}               


} 









相關文章