基于opencv的YUV图像转换为RGB图像
2014-12-24 15:48
483 查看
YUV2RGB格式转换
最近在arm板子上做一个项目,arm板上采集的图像是YUV格式的,在后续的图像处理中需要用到RGB格式的图像。在网上查了很多YUV转RGB的资料,由于每个人得到的YUV的数据排列格式不一样,所以要找到适合自己工程的代码很不容易。其中有两篇博客里的资料对我有很大启发,这里向大家介绍一下。网址如下:1. http://blog.csdn.net/dreamd1987/article/details/7259479#
2. http://blog.csdn.net/Lu597203933/article/details/23791177
网上普遍有两种方法,1. 通过opencv自带的cvCvtColor函数进行转换。2. 公式法。
1. opencv自带cvCvtColor
测试数据可以发文件问我要(我也是下载别人的测试数据)
测试文件名:football_cif.yuv, FOOTBALL_352x288_30_orig_01.yuv
图像大小:352*288
这两个文件的数据存储格式为:YUV,即先存储所有的Y,再存储所有的U,最后存储所有的V(非交叉存储)
具体代码如下:
#include <iostream> #include <highgui.h> #include <cv.h> #include <fstream> #include <sstream> using namespace std; #define FCount 10 #define ISizeX 352 //图像宽度 #define ISizeY 288 //图像高度 unsigned char Y[FCount][ISizeY][ISizeX]; unsigned char U[FCount][ISizeY/2][ISizeX/2]; unsigned char V[FCount][ISizeY/2][ISizeX/2]; // 将图片文件写入 void FileWriteFrames() { char *filename = "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); //读取Y分量 readMe.read((char*)U[nframes],ISizeX/2*ISizeY/2);//读取U分量 readMe.read((char*)V[nframes],ISizeX/2*ISizeY/2);//读取V分量 cvSetData(yimg,Y[nframes],ISizeX); cvSetData(uimg,U[nframes], ISizeX/2); cvSetData(vimg,V[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_YCrCb2RGB); // YUV转换为RGB stringstream ss; // 类型转换统一转换为char* 类型 ss << nframes; ss << ".jpg" ; ss >> nframesstr; cvShowImage("yuv", rgbimg); cvSaveImage(nframesstr,rgbimg); int c = cvWaitKey(300); if((char)c == 27) { break; } } readMe.close(); cvReleaseImage(&uuimg); <span style="white-space:pre"> </span>cvReleaseImage(&vvimg); cvReleaseImageHeader(&yimg); cvReleaseImageHeader(&uimg); cvReleaseImageHeader(&vimg); cvReleaseImage(&image); cvDestroyWindow("yuv"); } int main() { FileWriteFrames(); return 0; }
2. 公式法
测试数据:test1.bmp, test2.bmp(如有需要可以给我留言,留下你的邮箱)
数据存储格式:UYVY(交叉存储)
图像大小:1024*480
测试代码如下:
#include <iostream> #include <highgui.h> #include <cv.h> #include <fstream> #include <sstream> using namespace std; #define width 1024 //图像宽度 #define height 480 //图像高度 unsigned char *yuvtorgb24(char *bufyuv, int w, int h) { int r1,g1,b1,r2,g2,b2; int y1,u,v,y2; unsigned char *ps=(unsigned char *)bufyuv; unsigned char *pd; int len; if ((pd = (unsigned char *)malloc (w * h * 3)) == NULL) return NULL; len=w*h; while(len>0) { len-=2; u=*ps++; y1 =*ps++; v=*ps++; y2 =*ps++; r1=(10000*y1+14075*(v-128))/10000; g1=(10000*y1-3455*(u-128)-7169*(v-128))/10000; b1=(10000*y1+17990*(u-128))/10000; r2=(10000*y2+14075*(v-128))/10000; g2=(10000*y2-3455*(u-128)-7169*(v-128))/10000; b2=(10000*y2+17990*(u-128))/10000; if(r1>255)r1=255;if(r1<0)r1=0; if(g1>255)g1=255;if(g1<0)g1=0; if(b1>255)b1=255;if(b1<0)b1=0; if(r2>255)r2=255;if(r2<0)r2=0; if(g2>255)g2=255;if(g2<0)g2=0; if(b2>255)b2=255;if(b2<0)b2=0; *pd++=b1;*pd++=g1;*pd++=r1; *pd++=b2;*pd++=g2;*pd++=r2; } return pd-(w*h*3); } int main() { int i, j; unsigned char *p; char recvBuf[width*height*2]; IplImage *srcImg; char *filename = "test2.bmp"; srcImg = cvCreateImage(cvSize(width, height), 8, 3); cvZero(srcImg); ifstream fin(filename, ios::in | ios::binary); // 打开并读yuv数据 fin.read(recvBuf, width*height*2*sizeof(char)); /* 查看数据 for(i=0; i<500; i++) { unsigned char tmp = (unsigned char)recvBuf[i]; cout<< (unsigned short)tmp<<endl; } */ // yuv格式转换为rgb格式 p = yuvtorgb24(recvBuf, 1024, 480); // 图像颜色赋值 for(i=0; i<height; i++) { for(j=0; j<width; j++) { ((uchar *)(srcImg->imageData + i*srcImg->widthStep))[j*srcImg->nChannels + 0] = p[(i*width+j)*3 + 0]; ((uchar *)(srcImg->imageData + i*srcImg->widthStep))[j*srcImg->nChannels + 1] = p[(i*width+j)*3 + 1]; ((uchar *)(srcImg->imageData + i*srcImg->widthStep))[j*srcImg->nChannels + 2] = p[(i*width+j)*3 + 2]; } } free(p); cvSaveImage("mytest2.bmp", srcImg); cvNamedWindow("YUV2RGB", 1); cvShowImage("YUV2RGB", srcImg); cvWaitKey(0); cvReleaseImage(&srcImg); return 0; }
相关文章推荐
- YUV格式转换为RGB(基于opencv)
- YUV格式转换为RGB(基于opencv)
- (原创)用verilog实现RGB格式图像到YCbCr或YUV格式的转换及其验证方法 (RGB2YCrCb)(RGB2YUV)
- RGB与YUV图像视频格式的相互转换
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- 图像RGB与YUV转换优化
- 一个基于opencv的显示一个rgb图像各点灰度值及对应的灰度图象灰度值的程序
- 图像RGB与YUV转换优化
- YUY2(YUV) 与 RGB 格式图片的相互转换 以及 基于YUY2(YUV)的blending
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- RGB与YUV图像视频格式的相互转换
- YUY2(YUV) 与 RGB 格式图片的相互转换 以及 基于YUY2(YUV)的blending
- 基于OpenCV的RGB和HSV色彩空间相互转换C++程序
- RGB与YUV图像视频格式的相互转换(转)
- RGB彩色图像与灰度图像转换 opencv实现 代码及分析
- YUY2(YUV) 与 RGB 格式图片的相互转换 以及 基于YUY2(YUV)的blending
- YUY2(YUV) 与 RGB 格式图片的相互转换 以及 基于YUY2(YUV)的blending
- RGB与YUV图像视频格式的相互转换
- YUY2(YUV) 与 RGB 格式图片的相互转换 以及 基于YUY2(YUV)的blending