作者:masikkk
转自:http://blog.csdn.net/masibuaa/article/details/10004161
从网络摄像机中获取的帧数据是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;
- }
- }