您的位置:首页 > 其它

YUV420P转换为RGB32格式

2013-08-16 15:57 363 查看
从网络摄像机中获取的帧数据是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;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: