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 }
时间: 2024-10-09 22:34:34

YUV转为IplImage格式(I420和YV12)(转)的相关文章

怎么把Word文档转为PDF格式

怎么把Word文档转为PDF格式?现在的人大多数都喜欢用PDF格式来进行阅读,这是因为PDF文件有不错的视觉阅读性和保护性.但对于文员编辑来说,Word文档才是他们编辑资料的主要工具.有时候为了保障文件资料的安全,我们需要把编辑好Word文档转换成PDF格式,这样做主要是为了方便阅读和进行编辑和修改,同时大大的提高了我们的工作效率.那么问题来了,怎么把Word文档转为PDF格式呢?下面我们就一起来看看下面的介绍! 其实我们只需要一款专业的转换器就可以将Word文档转换成PDF格式."迅捷PDF转

js 时间戳转为日期格式

js 时间戳转为日期格式 什么是Unix时间戳(Unix timestamp): Unix时间戳(Unix timestamp),或称Unix时间(Unix time).POSIX时间(POSIX time),是一种时间表示方式,定义为从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数.Unix时间戳不仅被使用在Unix系统.类Unix系统中,也在许多其他操作系统中被广泛采用. 目前相当一部分操作系统使用32位二进制数字表示时间.此类系统的Unix时间戳最多可以使用到格林威治

YUY2(YUV) 与 RGB 格式图片的相互转换 以及 基于YUY2(YUV)的blending

这是一个项目里使用的,API里从pool里取出的格式都是YUY2,但是图像处理的API库中要求都是jepg格式. YUY2经常用于电视制式以及许多摄像头的输出格式.而我们在处理时经常需要将其转化为RGB进行处理,这里简单介绍下YUY2(YUV)与RGB之间相互转化的关系: http://msdn2.microsoft.com/en-us/library/ms893078.aspx YUY2(YUV) To RGB: C = Y - 16 D = U - 128 E = V - 128 R = c

js时间戳转为日期格式

这个在php+mssql(日期类型为datetime)+ajax的时候才能用到,js需要把时间戳转为为普通格式,一般的情况下可能用不到 [php] view plaincopy <script> function getLocalTime(nS) { return new Date(parseInt(nS) * 1000).toLocaleString().replace(/:\d{1,2}$/,' '); } alert(getLocalTime(1293072805)); </scr

php 实现html转为rtf格式

前期准备工作 下载Html2Rtf.dll,以管理员的身份运行cmd,进入Html2Rtf.dll所在目录-->输入Regsvr32 Html2Rtf.dll 核心代码: <?php $html2RTFCom = new COM("HTML2RTF.Converter"); $html2RTFCom->PreserveImages = true; $html2RTFCom->PageNumbers = 1; $html2RTFCom->PageNumber

通用的PDF转为Word格式的方法

PDF格式良好的视觉阅读性和通用性使得PDF文件的使用越来越广泛了,网络上的PDF资料也不少,但是我们常常希望可以对某些PDF资料里面的部分文字内容进行二次编辑,那么我们这里就是讲比较通用的PDF转为Word格式的方法. 使用迅捷PDF转换器: 首先,如果PDF是加密的,所以如果遇到已加密的PDF文件要先解密以后才可以转换的.这时你可以用pdf转换成word转换器,在项目栏选择PDF解密,添加需要转换的PDF文件,先将文件进行解密. 其次,怎么将PDF转换成Word.双击打开软件,进入操作界面,

png格式图片转为svg格式图片

png格式图片转为svg格式图片 (2012-08-30 16:24:00) 转载▼ 标签: 杂谈 分类: linux 在ubuntu下将png格式的图片转换成svg格式步骤如下:1.安装 inkscapesudo apt-get install inkscape2.安装 python-lxmlsudo apt-get install python-lxml3.使用 inkscape 打开png图像4.点中图像,选择命令 效果->图像->嵌入所有图像5.保存成svg格式

C# ffmpeg工具将视频转为SWF格式

1.下载ffmpeg工具 using System; using System.Collections; using System.Configuration; using System.Data; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls

js字符串转为日期格式

1. <script type="text/javascript"> //字符串转日期格式,strDate要转为日期格式的字符串 function getDate(strDate){ var date = eval('new Date(' + strDate.replace(/\d+(?=-[^-]+$)/, function (a) { return parseInt(a, 10) - 1; }).match(/\d+/g) + ')'); return date; }