数据压缩:yuv2rgb并通过rgb2yuv进行验证
来源:互联网 发布:sony 刷机软件 编辑:程序博客网 时间:2024/05/19 03:24
由电视原理可知RGB与YUV的关系:
Y=0.2990*R+0.5870*G+0.1140*B
R-Y=0.7010*R-0.5870*G-0.1140*B
B-Y=-0.2990*R-0.5870*G+0.8860*B
归一化后:
U=-0.1684*R-0.3316*G+0.5*B
V=0.5*R-0.4187*G-0.0813*b
则 R=Y+(R-Y)= Y + 1.4075 *(V-128)
G = Y+(G-Y)=Y-0.3455*(U-128)-0.7169(V-128)
B =Y+(B-Y)= Y + 1.779 *(U-128)
存储格式:
RGB24格式的图像采用打包存储方法:即一个像素点的数据连续存放,且存储顺序并非字面顺序,而是:BGRBGRBGR..........
YUV420则是分别存储,现存储所有的Y分量,然后是U分量、V分量。
数据量:
RGB24用24位来表示一个像素,分量用8位表示,取值范围是0~255.一帧RGB所占用的空间为:width*height*3
YUV420中Y是灰度图像,U、V分量的高度和宽度分别是Y分量的一半,则一帧YUV所占内存的大小为:weight*height*3/2.
实现流程:先实现YUV向RGB的转换,再对YUV进行上采样(RGB到YUV则是下采样)
yuv2rgb的部分代码(在之前给定的rgb2yuv的基础上修改得来):
#include "stdlib.h"#include "yuv2rgb.h"static float YUVRGB14075[256];static float YUVRGB03455[256], YUVRGB07169[256];static float YUVRGB1779[256];int YUV2RGB (int x_dim, int y_dim, void *y_in, void *u_in, void *v_in,void *bmp, int flip){static int init_done = 0;long i, j, size;unsigned char *r, *g, *b;float r_temp,g_temp,b_temp;unsigned char *y, *u, *v;unsigned char *u_buffer, *v_buffer;unsigned char *sub_y_buf,*sub_u_buf, *sub_v_buf; if (init_done == 0) { InitLookupTable();//运行查找表子程序 init_done = 1; }// check to see if x_dim and y_dim are divisible by 2,查看是否可以被2整除if ((x_dim % 2) || (y_dim % 2)) return 1;//如果不能被2 整除,则return1size = x_dim * y_dim;// allocate memorysub_y_buf = (unsigned char *)y_in;sub_u_buf = (unsigned char *)u_in;sub_v_buf = (unsigned char *)v_in;u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));//分配指定字节的内存空间v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));if (!(u_buffer && v_buffer)){if (u_buffer) free(u_buffer);//如果其中任何一个没有分配内存空间,就释放if (v_buffer) free(v_buffer);return 2;}b = (unsigned char *)bmp;//b指向bmp文件的首地址的指针y = sub_y_buf;u = sub_u_buf;v = sub_v_buf;// 倒序if (!flip) {/*for (j = 0; j < y_dim; j ++){y = y_buffer + (y_dim - j - 1) * x_dim;u = u_buffer + (y_dim - j - 1) * x_dim;v = v_buffer + (y_dim - j - 1) * x_dim;for (i = 0; i < x_dim; i ++) {g = b + 1;r = b + 2;*y = (unsigned char)( RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);*u = (unsigned char)(- RGBYUV01684[*r] - RGBYUV03316[*g] + (*b)/2 + 128);*v = (unsigned char)( (*r)/2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);b += 3;y ++;u ++;v ++;}}*///倒序} else {for (j = 0; j < y_dim; j++)//行{for (i = 0; i < x_dim; i++)//列{g = b + 1;//顺序为BGRBGRBGR.....r = b + 2;r_temp= ((*y)+ YUVRGB14075[*v] );//计算rgbg_temp= ((*y)-YUVRGB03455[*u] - YUVRGB07169[*v] );b_temp= ((*y) + YUVRGB1779[*u] );//判断计算结果是否在0-255范围内(8)if(r_temp>255)*r=(unsigned char)(255);else if(r_temp<0)*r=(unsigned char)(0);else *r=(unsigned char)(r_temp);if(g_temp>255)*g=(unsigned char)(255);else if(g_temp<0)*g=(unsigned char)(0);else *g=(unsigned char)(g_temp);if(b_temp>255)*b=(unsigned char)(255);else if(b_temp<0)*b=(unsigned char)(0);else *b=(unsigned char)(b_temp);b += 3;y ++;u =sub_u_buf+(j/2)*x_dim/2+i/2;v =sub_v_buf+(j/2)*x_dim/2+i/2;}}}return 0;}// 上采样/*for (j = 0; j < y_dim/2; j ++){psu = sub_u_buf + j * x_dim / 2;//行指针psv = sub_v_buf + j * x_dim / 2;pu1 = u_buffer + 2 * j * x_dim;//u_buffer内存空间,2* j * x_dim代表隔两行取一行pu2 = u_buffer + (2 * j + 1) * x_dim;//指向(取样的)下一行pv1 = v_buffer + 2 * j * x_dim;pv2 = v_buffer + (2 * j + 1) * x_dim;for (i = 0; i < x_dim/2; i ++){*psu = (*pu1 + *(pu1+1) + *pu2 + *(pu2+1)) / 4;//每四个取一个*psv = (*pv1 + *(pv1+1) + *pv2 + *(pv2+1)) / 4;psu ++;psv ++;pu1 += 2;pu2 += 2;pv1 += 2;pv2 += 2;}}free(u_buffer);//释放内存空间free(v_buffer);return 0;}*/void InitLookupTable()//查找表{int i;for (i = 0; i < 256; i++) YUVRGB14075[i] = (float)1.4075 * (i-128);for (i = 0; i < 256; i++) YUVRGB03455[i] = (float)0.3455 * (i-128);for (i = 0; i < 256; i++) YUVRGB07169[i] = (float)0.7169 * (i-128);for (i = 0; i < 256; i++) YUVRGB1779[i] = (float)1.779 * (i-128);}
部分main.cpp代码:
/* get an output buffer for a frame */rgbBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 3);//内存空间/* get the input buffers for a frame */yBuf = (u_int8_t*)malloc(frameWidth * frameHeight);uBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);vBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);if (rgbBuf == NULL || yBuf == NULL || uBuf == NULL || vBuf == NULL){printf("no enought memory\n");exit(1);}//读文件fread(yBuf, 1, frameWidth * frameHeight , yuvFile);fread(uBuf, 1, frameWidth * frameHeight/4 , yuvFile);fread(vBuf, 1, frameWidth * frameHeight/4 , yuvFile);if(YUV2RGB(frameWidth, frameHeight, yBuf, uBuf, vBuf,rgbBuf, flip)){printf("error");return 0;}if(fwrite(rgbBuf, 1, frameWidth * frameHeight*3, rgbFile)){printf("\r...%d", ++videoFramesWritten);printf("\n%u %ux%u video frames written\n",videoFramesWritten, frameWidth, frameHeight);}/* cleanup */if (rgbFile) fclose(rgbFile); if (yuvFile) fclose(yuvFile);if (rgbBuf) free(rgbBuf); if (yBuf) free(yBuf); if (uBuf) free(uBuf); if (vBuf) free(vBuf);return(0);
实验中出现的问题:
1.
将yuv文件转成rgb图像后,理论上应与原图像的大小(192kB)一致,但实际比原图像要大(248kB),后将参数修改后便可正常显示。
错误参数如下:
2 修改参数后又发现新的错误,即yuv转rgb,再转yuv后图像与原图像色差较大
经参考rgb2yuv文件的代码后,发现应该是U和V指针有误,反复修改后得如下结果:
u =sub_u_buf+(j/2)*x_dim/2+i/2;
v =sub_v_buf+(j/2)*x_dim/2+i/2;
3为进行rgb像素取值是否在0~255之间的判断,但并未觉察出较大的差异,在浏览了网上的部分代码后,增加了该部分判断。
(未判断) (判断)
其他文件的测试:
第一幅为176x144,后两幅为352x288,所选文件均为多帧,处理后仅有1帧
- 数据压缩:yuv2rgb并通过rgb2yuv进行验证
- 【数据压缩】RGB2YUV/YUV2RGB实验报告
- RGB2YUV/YUV2RGB
- formula YUV2RGB RGB2YUV
- 【数据压缩】yuv2rgb
- 图像RGB2YUV与YUV2RGB格式互转介绍
- 《数据压缩》实验报告一·YUV2RGB实验
- rgb2yuv
- Rgb2Yuv
- RGB2YUV
- 数据压缩原理与应用 彩色空间转换RGB2YUV
- 数据压缩实验一:彩色空间转换实验(yuv2rgb)
- 【数据压缩】Exp01.彩色空间转换——YUV2RGB
- YUV2RGB
- yuv2rgb
- YUV2RGB
- YUV2RGB
- yuv2rgb
- 【斯坦福大学-机器学习】1.引言
- RFT
- 模糊查询时候xml判断数据库类型的写法
- Go语言-并发通信
- 如何运行Struts2官网最新Demo-
- 数据压缩:yuv2rgb并通过rgb2yuv进行验证
- Java Socket编程----通信是这样炼成的
- Nginx下出现Access denied (403) see security.limit_extensions错误的解决方法
- 为什么pageHelper超过最大页数后还会返回数据
- GYM 100883 C.Too Many Coins(水~)
- windows下Gradle安装
- oracle中的递归查询
- 前端学HTTP之客户端识别和cookie
- 【第十一课】异常---异常与继承