• 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#

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

  • 相关阅读:
    Codeforces Round #213 (Div. 2) B. The Fibonacci Segment
    关于求解不定方程的n(n-1)=2m(m-1)的解法的总结
    objective-c @()
    objective-c 条件运算符
    关于判断两个矩阵相交的一点想法
    二维几何常用运算
    《为ipad而设计 打造畅销APP》读书笔记
    ios cocos2d FPS过低的解决方法
    python 根据对象和方法名,返回提供这个方法的定义的类
    python 获取类的属性
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4676621.html
Copyright © 2020-2023  润新知