YUV转为IplImage格式(I420和YV12)(转)

一、YUV简介
    一般来说,直接采集到的视频数据是RGB24的格式,RGB24一帧的大小size=width×heigth×3 Byte,RGB32的size=width×heigth×4 Byte,如果是I420(即YUV标准格式4:2:0)的数据量是 size=width×heigth×1.5 Byte。 在采集到RGB24数据后,需要对这个格式的数据进行第一次压缩。即将图像的颜色空间由RGB24转化为IYUV。因为,X264在进行编码的时候需要标准的YUV(4:2:0)。但是这里需要注意的是,虽然YV12也是(4:2:0),但是YV12和I420的却是不同的,在存储空间上面有些区别。如下:
    YV12 : 亮度(行×列) + V(行×列/4) + U(行×列/4)
    I420 : 亮度(行×列) + U(行×列/4) + V(行×列/4)

可以看出,YV12和I420基本上是一样的,就是UV的顺序不同。
    YUV420p 和 YUV420的区别在于存储格式上有区别:
    YUV420p:yyyyyyyy uuuu vvvvv
    YUV420: yuv yuv yuv

     关于YUV 更详细资料可参考:http://zh.wikipedia.org/wiki/YUV。
    另外,需要注意的是海康设备回调数据类型为YV12格式;而大华设备回调数据类型为YUV420格式。

二、YUV420转IplImage

采用OpenCV转换的方式,代码如下:

 1 IplImage* YUV420_To_IplImage_Opencv(unsigned char* pYUV420, int width, int height)
 2 {
 3     if (!pYUV420)
 4     {
 5         return NULL;
 6     }
 7 
 8     IplImage *yuvimage,*rgbimg,*yimg,*uimg,*vimg,*uuimg,*vvimg;
 9 
10     int nWidth = width;
11     int nHeight = height;
12     rgbimg = cvCreateImage(cvSize(nWidth, nHeight),IPL_DEPTH_8U,3);
13     yuvimage = cvCreateImage(cvSize(nWidth, nHeight),IPL_DEPTH_8U,3);
14 
15     yimg = cvCreateImageHeader(cvSize(nWidth, nHeight),IPL_DEPTH_8U,1);
16     uimg = cvCreateImageHeader(cvSize(nWidth/2, nHeight/2),IPL_DEPTH_8U,1);
17     vimg = cvCreateImageHeader(cvSize(nWidth/2, nHeight/2),IPL_DEPTH_8U,1);
18 
19     uuimg = cvCreateImage(cvSize(nWidth, nHeight),IPL_DEPTH_8U,1);
20     vvimg = cvCreateImage(cvSize(nWidth, nHeight),IPL_DEPTH_8U,1);
21 
22     cvSetData(yimg,pYUV420, nWidth);
23     cvSetData(uimg,pYUV420+nWidth*nHeight, nWidth/2);
24     cvSetData(vimg,pYUV420+long(nWidth*nHeight*1.25), nWidth/2);
25     cvResize(uimg,uuimg,CV_INTER_LINEAR);
26     cvResize(vimg,vvimg,CV_INTER_LINEAR);
27 
28     cvMerge(yimg,uuimg,vvimg,NULL,yuvimage);
29     cvCvtColor(yuvimage,rgbimg,CV_YCrCb2RGB);
30 
31     cvReleaseImage(&uuimg);
32     cvReleaseImage(&vvimg);
33     cvReleaseImageHeader(&yimg);
34     cvReleaseImageHeader(&uimg);
35     cvReleaseImageHeader(&vimg);
36 
37     cvReleaseImage(&yuvimage);
38 
39     if (!rgbimg)
40     {
41         return NULL;
42     }
43 
44     return rgbimg;
45 }

采用数学转换的方式,代码如下:

  1 bool YUV420_To_BGR24(unsigned char *puc_y, unsigned char *puc_u, unsigned char *puc_v, unsigned char *puc_rgb, int width_y, int height_y)
  2 {
  3     if (!puc_y || !puc_u || !puc_v || !puc_rgb)
  4     {
  5         return false;
  6     }
  7     
  8     //初始化变量
  9     int baseSize = width_y * height_y;
 10     int rgbSize = baseSize * 3;
 11 
 12     BYTE* rgbData  = new BYTE[rgbSize];
 13     memset(rgbData, 0, rgbSize);
 14 
 15     /* 变量声明 */
 16     int temp = 0;
 17 
 18     BYTE* rData = rgbData;                  //r分量地址
 19     BYTE* gData = rgbData + baseSize;       //g分量地址
 20     BYTE* bData = gData   + baseSize;       //b分量地址
 21 
 22     int uvIndex =0, yIndex =0;
 23 
 24     //YUV->RGB 的转换矩阵
 25     //double  Yuv2Rgb[3][3] = {1, 0, 1.4022,
 26     //    1, -0.3456, -0.7145,
 27     //    1, 1.771,   0};
 28 
 29     for(int y=0; y < height_y; y++)
 30     {
 31         for(int x=0; x < width_y; x++)
 32         {
 33             uvIndex        = (y>>1) * (width_y>>1) + (x>>1);
 34             yIndex         = y * width_y + x;
 35 
 36             /* r分量 */
 37             temp          = (int)(puc_y[yIndex] + (puc_v[uvIndex] - 128) * 1.4022);
 38             rData[yIndex] = temp<0 ? 0 : (temp > 255 ? 255 : temp);
 39 
 40             /* g分量 */
 41             temp          = (int)(puc_y[yIndex] + (puc_u[uvIndex] - 128) * (-0.3456) +
 42                 (puc_v[uvIndex] - 128) * (-0.7145));
 43             gData[yIndex] = temp < 0 ? 0 : (temp > 255 ? 255 : temp);
 44 
 45             /* b分量 */
 46             temp          = (int)(puc_y[yIndex] + (puc_u[uvIndex] - 128) * 1.771);
 47             bData[yIndex] = temp < 0 ? 0 : (temp > 255 ? 255 : temp);
 48         }
 49     }
 50 
 51     //将R,G,B三个分量赋给img_data
 52     int widthStep = width_y*3;
 53     for (int y = 0; y < height_y; y++)
 54     {
 55         for (int x = 0; x < width_y; x++)
 56         {
 57             puc_rgb[y * widthStep + x * 3 + 2] = rData[y * width_y + x];   //R
 58             puc_rgb[y * widthStep + x * 3 + 1] = gData[y * width_y + x];   //G
 59             puc_rgb[y * widthStep + x * 3 + 0] = bData[y * width_y + x];   //B
 60         }
 61     }
 62 
 63     if (!puc_rgb)
 64     {
 65         return false;
 66     }
 67 
 68     delete [] rgbData;
 69     return true;
 70 }
 71 
 72 IplImage* YUV420_To_IplImage(unsigned char* pYUV420, int width, int height)
 73 {
 74     if (!pYUV420)
 75     {
 76         return NULL;
 77     }
 78 
 79     //初始化变量
 80     int baseSize = width*height;
 81     int imgSize = baseSize*3;
 82 
 83 BYTE* pRGB24  = new BYTE[imgSize];
 84 memset(pRGB24,  0, imgSize);
 85 
 86     /* 变量声明 */
 87     int temp = 0;
 88 
 89     BYTE* yData = pYUV420;                  //y分量地址
 90     BYTE* uData = pYUV420 + baseSize;       //u分量地址
 91     BYTE* vData = uData  + (baseSize>>2);   //v分量地址
 92 
 93     if(YUV420_To_BGR24(yData, uData, vData, pRGB24, width, height) == false || !pRGB24)
 94     {
 95         return NULL;
 96     }
 97 
 98     IplImage *image = cvCreateImage(cvSize(width, height), 8,3);
 99     memcpy(image->imageData, pRGB24, imgSize);
100 
101     if (!image)
102     {
103         return NULL;
104     }
105 
106     delete [] pRGB24;
107     return image;
108 }

三、YV12转IplImage

  1 //YV12转为BGR24数据
  2 bool YV12_To_BGR24(unsigned char* pYV12, unsigned char* pRGB24,int width, int height)
  3 {
  4     if(!pYV12 || !pRGB24)
  5     {
  6         return false;
  7     }
  8 
  9     const long nYLen = long(height * width);
 10     const int halfWidth = (width>>1);
 11 
 12     if(nYLen<1 || halfWidth<1)
 13     {
 14         return false;
 15     }
 16 
 17     // yv12's data structure
 18     // |WIDTH |
 19     // y......y--------
 20     // y......y   HEIGHT
 21     // y......y
 22     // y......y--------
 23     // v..v
 24     // v..v
 25     // u..u
 26     // u..u
 27     unsigned char* yData = pYV12;
 28     unsigned char* vData = &yData[nYLen];
 29     unsigned char* uData = &vData[nYLen>>2];
 30 
 31     if(!uData || !vData)
 32     {
 33         return false;
 34     }
 35 
 36     // Convert YV12 to RGB24
 37     int rgb[3];
 38     int i, j, m, n, x, y;
 39     m = -width;
 40     n = -halfWidth;
 41     for(y=0; y<height;y++)
 42     {
 43         m += width;
 44             if(!(y % 2))
 45                 n += halfWidth;
 46         for(x=0; x<width;x++)   
 47         {
 48             i = m + x;
 49                 j = n + (x>>1);
 50             rgb[2] = int(yData[i] + 1.370705 * (vData[j] - 128)); // r
 51             rgb[1] = int(yData[i] - 0.698001 * (uData[j] - 128)  - 0.703125 * (vData[j] - 128));   // g
 52             rgb[0] = int(yData[i] + 1.732446 * (uData[j] - 128)); // b
 53 
 54             //j = nYLen - iWidth - m + x;
 55             //i = (j<<1) + j;    //图像是上下颠倒的
 56 
 57             j = m + x;
 58             i = (j<<1) + j;
 59 
 60             for(j=0; j<3; j++)
 61             {
 62                 if(rgb[j]>=0 && rgb[j]<=255)
 63                     pRGB24[i + j] = rgb[j];
 64                 else
 65                     pRGB24[i + j] = (rgb[j] < 0)? 0 : 255;
 66             }
 67         }
 68     }
 69 
 70     if (pRGB24 == NULL)
 71     {
 72         return false;
 73     }
 74 
 75     return true;
 76 }
 77 
 78 
 79 IplImage* YV12_To_IplImage(unsigned char* pYV12, int width, int height)
 80 {
 81     if (!pYV12)
 82     {
 83         return NULL;
 84     }
 85 
 86     int sizeRGB = width* height *3;
 87     unsigned char* pRGB24 = new unsigned char[sizeRGB];
 88     memset(pRGB24, 0, sizeRGB);
 89 
 90     if(YV12_To_BGR24(pYV12, pRGB24 ,width, height) == false || (!pRGB24))
 91     {
 92         return NULL;
 93     }
 94 
 95     IplImage* pImage = cvCreateImage(cvSize(width, height), 8, 3);
 96     if(!pImage)
 97     {
 98         return NULL;
 99     }
100 
101     memcpy(pImage->imageData, pRGB24, sizeRGB);
102     if (!(pImage->imageData))
103     {
104         return NULL;
105     }
106 
107     delete [] pRGB24;
108     return pImage;
109 }

 

转载于:https://www.cnblogs.com/clownxy/p/3986340.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值