从网络摄像机中获取的帧数据是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; }
将代码中的给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; } }