YUV格式转换RGB(基于opencv)

在编写代码将需要处理YUV格从每个视频帧中提取,然后将其保存为图片。有两种常见的方法在线,第一种是通过opencv自带cvCvtColor,可是这样的方法有bug。得到的图片会泛白。另外一种方法是公式法。

法一:opencv自带cvCvtColor

说明:这样的方法会出现图片“泛白”。详细原因网上是说cvCvtColor这个函数左右协议不同,不太懂。

代码:

void FileWriteFrames(){
	char *filename = "E:\\openCV\\zhang\\yuvSource\\football_cif.yuv";
	ifstream readMe(filename, ios::in | ios::binary);  // 打开并读yuv数据
	IplImage *image, *rgbimg, *yimg, *uimg, *vimg, *uuimg, *vvimg;
	cvNamedWindow("yuv",CV_WINDOW_AUTOSIZE);
	rgbimg = cvCreateImage(cvSize(ISizeX, ISizeY), IPL_DEPTH_8U, 3);
	image = cvCreateImage(cvSize(ISizeX, ISizeY), IPL_DEPTH_8U, 3);

	yimg = cvCreateImageHeader(cvSize(ISizeX, ISizeY), IPL_DEPTH_8U, 1);    // 亮度分量
	uimg = cvCreateImageHeader(cvSize(ISizeX/2, ISizeY/2), IPL_DEPTH_8U, 1);  // 这两个都是色度分量
	vimg = cvCreateImageHeader(cvSize(ISizeX/2, ISizeY/2), IPL_DEPTH_8U, 1);

	uuimg = cvCreateImage(cvSize(ISizeX, ISizeY), IPL_DEPTH_8U, 1);
	vvimg = cvCreateImage(cvSize(ISizeX, ISizeY), IPL_DEPTH_8U, 1);
	int nframes;
	for(nframes = 0; nframes < FCount; nframes ++){
		char nframesstr[20];
		readMe.read((char*)Y[nframes],ISizeX*ISizeY);
		//readMe.seekg(-ISizeX*ISizeY, ios::cur);
		//readMe.read((char*)buf[nframes],ISizeX*ISizeY+ISizeX/2*ISizeY/2+ISizeX/2*ISizeY/2);
		readMe.read((char*)buf[nframes],ISizeX/2*ISizeY/2);
		readMe.read((char*)buf2[nframes],ISizeX/2*ISizeY/2);
		cvSetData(yimg,Y[nframes],ISizeX);
		//cvSetData(uimg,buf[nframes] + ISizeX*ISizeY, ISizeX/2);
		cvSetData(uimg,buf[nframes], ISizeX/2);
		cvSetData(vimg,buf2[nframes], ISizeX/2);

		cvResize(uimg,uuimg, CV_INTER_LINEAR);
		cvResize(vimg,vvimg, CV_INTER_LINEAR);
		cvMerge(yimg,uuimg,vvimg,NULL,image);   // 合并单通道为三通道
		cvCvtColor(image,rgbimg,CV_YUV2BGR);    

		stringstream ss;  // 类型转换统一转换为char* 类型
		ss << nframes;
		ss << ".jpg" ;
		ss >> nframesstr;
		cvShowImage("yuv", rgbimg);
		cvSaveImage(nframesstr,rgbimg);
		int c = cvWaitKey(30);
		if((char)c == 27)
		{
			break;
		}
	}
	readMe.close();
	cvReleaseImage(&uuimg);
    cvReleaseImage(&vvimg);
	cvReleaseImageHeader(&yimg);
	cvReleaseImageHeader(&uimg);
	cvReleaseImageHeader(&vimg);
	cvReleaseImage(&image);
	cvDestroyWindow("yuv");
}

法二:公式法

代码:

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)
{
    if (!puc_y || !puc_u || !puc_v || !puc_rgb)
    {
        return false;
    }

    //初始化变量
    int baseSize = width_y * height_y;
    int rgbSize = baseSize * 3;

    BYTE* rgbData  = new BYTE[rgbSize];
    memset(rgbData, 0, rgbSize);

    /* 变量声明 */
    int temp = 0;

    BYTE* rData = rgbData;                  //r分量地址
    BYTE* gData = rgbData + baseSize;       //g分量地址
    BYTE* bData = gData   + baseSize;       //b分量地址

    int uvIndex =0, yIndex =0;

    //YUV->RGB 的转换矩阵
    //double  Yuv2Rgb[3][3] = {1, 0, 1.4022,
    //    1, -0.3456, -0.7145,
    //    1, 1.771,   0};

    for(int y=0; y < height_y; y++)
    {
        for(int x=0; x < width_y; x++)
        {
            uvIndex        = (y>>1) * (width_y>>1) + (x>>1);
            yIndex         = y * width_y + x;

            /* r分量 */
            temp          = (int)(puc_y[yIndex] + (puc_v[uvIndex] - 128) * 1.4022);
            rData[yIndex] = temp<0 ?

0 : (temp > 255 ? 255 : temp);

            /* g分量 */
            temp          = (int)(puc_y[yIndex] + (puc_u[uvIndex] - 128) * (-0.3456) +
                (puc_v[uvIndex] - 128) * (-0.7145));
            gData[yIndex] = temp < 0 ? 0 : (temp > 255 ?

255 : temp);

            /* b分量 */
            temp          = (int)(puc_y[yIndex] + (puc_u[uvIndex] - 128) * 1.771);
            bData[yIndex] = temp < 0 ? 0 : (temp > 255 ? 255 : temp);
        }
    }

    //将R,G,B三个分量赋给img_data
    int widthStep = width_y*3;
    for (int y = 0; y < height_y; y++)
    {
        for (int x = 0; x < width_y; x++)
        {
			puc_rgb[y * widthStep + x * 3 + 2] = rData[y * width_y + x];   //R
            puc_rgb[y * widthStep + x * 3 + 1] = gData[y * width_y + x];   //G
            puc_rgb[y * widthStep + x * 3 + 0] = bData[y * width_y + x];   //B
        }
    }

    if (!puc_rgb)
    {
        return false;
    }
    delete [] rgbData;
    return true;
}

IplImage* YUV420_To_IplImage(unsigned char* pYUV420, int width, int height)
{
    if (!pYUV420)
    {
		return NULL;
    }

    //初始化变量
    int baseSize = width*height;
    int imgSize = baseSize*3;
	BYTE* pRGB24  = new BYTE[imgSize];
	memset(pRGB24,  0, imgSize);

    /* 变量声明 */
    int temp = 0;

    BYTE* yData = pYUV420;                  //y分量地址
    BYTE* uData = pYUV420 + baseSize;       //u分量地址
    BYTE* vData = uData  + (baseSize>>2);   //v分量地址

    if(YUV420_To_BGR24(yData, uData, vData, pRGB24, width, height) == false || !pRGB24)
    {
		return NULL;
	}

    IplImage *image = cvCreateImage(cvSize(width, height), 8,3);
    memcpy(image->imageData, pRGB24, imgSize);

    if (!image)
    {
        return NULL;
    }

    delete [] pRGB24;
    return image;
}

void FileWriteFrames(){
	char *filename = "E:\\openCV\\zhang\\yuvSource\\FOOTBALL_352x288_30_orig_01.yuv";
	ifstream readMe(filename, ios::in | ios::binary);  // 打开并读yuv数据
	int nframes;
	for(nframes = 0; nframes < FCount; nframes ++){
		char nframesstr[20];
		readMe.read((char*)Y[nframes],ISizeX*ISizeY);
		readMe.seekg(-ISizeX*ISizeY, ios::cur);
		readMe.read((char*)buf[nframes],ISizeX*ISizeY+ISizeX/2*ISizeY/2+ISizeX/2*ISizeY/2);
		IplImage *rgbimg = YUV420_To_IplImage(buf[nframes], ISizeX, ISizeY);
		stringstream ss;  // 类型转换统一转换为char* 类型
		ss << nframes;
		ss << ".jpg" ;
		ss >> nframesstr;
		cvShowImage("yuv", rgbimg);
		cvSaveImage(nframesstr,rgbimg);
		int c = cvWaitKey(30);
		if((char)c == 27)
		{
			break;
		}
	}
	readMe.close();
}

完整代码见:http://download.csdn.net/detail/lu597203933/7362687

參见blog:http://blog.csdn.net/dreamd1987/article/details/7259479#

版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2024-10-20 02:13:49

YUV格式转换RGB(基于opencv)的相关文章

YUV格式转换为RGB(基于opencv)

之前写代码过程中需要将YUV格式视频中每帧提取出来,然后保存为图片.网上普遍有两种方法,第一种是通过opencv自带cvCvtColor,但是这种方法有bug,得到的图片会泛白.第二种方法是公式法. 法一:opencv自带cvCvtColor 说明:这种方法会出现图片"泛白",具体原因网上是说cvCvtColor这个函数左右协议不同,不太懂. 代码: void FileWriteFrames(){ char *filename = "E:\\openCV\\zhang\\yu

YUV 格式与 RGB 格式的相互转换公式及C++ 代码

YUV 格式与 RGB 格式的相互转换公式 最近在用的一个工业相机,输出的图像格式是 YUY2 格式.而在电脑上显示时需要 RGB 格式,所以就花了些时间在网上查了些相关的资料.说实话,网上关于 YUV 与 RGB 格式变换的文章挺多的,本来不需要我再多写这么一篇.但是网上那些文章中给出了各种各样的变换公式,公式的系数又各不相同,让人看了之后越看越糊涂.其实那些文章的公式基本都是对的,只不过因为作者忘记给出变换公式的定义域与值域,所以给读者使用造成了很大的麻烦. 为此我就写了这篇文章,来梳理一下

微信小程序使用wxs在页面中调用js函数,颜色值格式转换 rgb和十六进制的转换

<wxs module="filter"> var filter = { numberToFix: function (hex) { // 16进制颜色值的正则 // var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; var reg = getRegExp('^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$','g'); console.log(reg); console.log('结束'); // 把颜色值

【视频处理】YUV与RGB格式转换

YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与YUV的变换公式如下: YUV(256 级别) 可以从8位 RGB 直接计算: Y = 0.299 R + 0.587 G + 0.114 B U = - 0.1687 R - 0.3313 G + 0.5 B + 128 V = 0.5 R - 0.4187 G - 0.0813 B + 128 反过来,RGB 也可以直接从YUV

YUV与RGB格式转换

YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与YUV的变换公式如下: YUV(256 级别) 可以从8位 RGB 直接计算: Y = 0.299 R + 0.587 G + 0.114 B U = - 0.1687 R - 0.3313 G + 0.5 B + 128 V = 0.5 R - 0.4187 G - 0.0813 B + 128 反过来,RGB 也可以直接从YUV

一款开源的 Android YUV 格式查看工具

1. YUVDroidTools 最近项目比较忙,好久没有写文章了,也没有为开源社区贡献点啥了,这个周末抽空整理了一下自己一直维护的一份基于 ffmpeg 的 YUV 格式转换代码,写了一个简单的 Android YUV 数据查看工具(代码完全开源),截图如下: 特性如下: (1)支持选择导入本地文件,支持实时显示 YUV 格式的图片,简单易用. (2)支持多种 YUV 格式,包括: YU12.YV12.NV21.NV12.YUYV422.YVYU422.YUV422P.UYVY422 等等.

YUV格式&amp;像素

一幅彩色图像的基本要素是什么? 说白了,一幅图像包括的基本东西就是二进制数据,其容量大小实质即为二进制数据的多少.一幅1920x1080像素的YUV422的图像,大小是1920X1080X2=4147200(十进制),也就是3.95M大小.这个大小跟多少个像素点和数据的存储格式有关.下面简述yuv与像素的关系: YUV与像素的关系: YUV是利用一个亮度(Y).两个色差(U,V)来代替传统的RGB三原色来压缩图像.传统的RGB三原色使用红绿蓝三原色表示一个像素,每种原色占用一个字节(8bit),

YUV RGB 格式转换

第一个公式是RGB转YUV(范围0-255)时用的,第二个公式是用在YUV转换RGB(范围0-255)时用的.1. Y = 0.257 * R + 0.504 * G + 0.098 * B + 16; U = -0.148 * R - 0.291 * G + 0.439 * B + 128; V = 0.439 * R - 0.368 * G - 0.071 * B + 128; 黑色:Y=16 ,U= V =128 红色:Y=82 ,U=90,V=240 绿色:Y=145,U=54,V=34

YUYV格式到RGB格式的转换

为什么YUYV格式要转到RGB格式,视频的显示调用的多数API都是基于RGB格式,所以需要进行格式的转换. YUYV格式如下: Y0U0Y1V0 Y2U1Y3V1.......... 说明:一个Y代表一个像素,而一个Y和UV组合起来构成一个像素,所以第0个像素Y0和第一个像素Y1都是共用第0个像素的U0和V0.而每个分量Y,U,V都是占用一个字节的存储空间.所以Y0U0Y1V0相当于两个像素,占用了4个字节的存储空间,平均一个像素占用两个字节. RGB格式: R0G0B0 R1G1B1.....