《数据压缩》实验报告一·YUV2RGB实验

    xiaoxiao2021-03-25  63

    一.实验原理

    (1)YUV与RGB空间的相互转换

               亮度和色差信号的构成如下:

               Y =  0.2990R + 0.5870G +  0.1140B

          R-Y =  0.7010R  -  0.5870G -  0.1140B

          B-Y = -0.2990R  -  0.5870G + 0.8860B

           为了使色差信号的动态范围控制在0.5之间,需要进行归一化,对色差信号引入压缩系数。归一化后的色差信号为:

              U = -0.1684R - 0.3316G + 0.5B

              V =          0.5R - 0.4187G - 0.0813B

           由此可得YUV转RGB公式:

            R = Y + 1.14075(V - 128)

            G = Y - 0.7169(V - 128) - 0.3455(U - 128)

            B = Y + 1.779(U - 128)

    (2)存储方式与所占空间

           一帧YUV图像在存储方式上,先存这一帧所有的Y数据,再存这一帧所有的U数据,最后存这一帧所有的V数据。YUV的取样格式为4:2:0(即色差信号U,V的取样频率为亮度信号取样频率的四分之一,在水平方向和垂直方向上的取样点数均为Y的一半),所以一帧YUV图像所占空间大小为: 宽x高x1.5。

           而RGB在存储方式上,按照B,G,R的顺序,连续存储每个像素的BGR数据,所以一帧RGB所占空间大小为: 宽x高x3。

           因此,在RGB转YUV的实验中需用下采样的方式;在YUV转RGB的实验中需要用上采样的方式

    二.实验流程分析

    1.程序初始化(打开两个文件,定义变量和缓冲区)

    2.读取YUV文件,抽取YUV数据写入缓冲区

    3.调用YUV2RGB的函数实现YUV到RGB数据的转换

    4.写RGB文件

    5.程序收尾工作(关闭文件,释放缓冲区)

    三.关键代码及其分析

    main.cpp与yuv2rgb.cpp

    #include #include #include #include "yuv2rgb.h" #define u_int8_t unsigned __int8 #define u_int unsigned __int32 #define u_int32_t unsigned __int32 #define FALSE false #define TRUE true int main(int argc, char** argv) { u_int frameWidth = 352; u_int frameHeight = 240; char* rgbFileName = NULL; char* yuvFileName = NULL; FILE* rgbFile = NULL; FILE* yuvFile = NULL; u_int8_t* rgbBuf = NULL; u_int8_t* yBuf = NULL; u_int8_t* uBuf = NULL; u_int8_t* vBuf = NULL; u_int32_t videoFramesWritten = 0; yuvFileName = argv[1]; rgbFileName = argv[2]; frameWidth = atoi(argv[3]); frameHeight = atoi(argv[4]); /* open the YUV file */ yuvFile = fopen(yuvFileName, "rb"); if (yuvFile == NULL) { printf("cannot find yuv file\n"); exit(1); } else { printf("The input yuv file is %s\n",yuvFileName); } /* open the RAW file */ rgbFile = fopen(rgbFileName, "wb"); if (rgbFile == NULL) { printf("cannot find rgb file\n"); exit(1); } else { printf("The output rgb file is %s\n", rgbFileName); } /* get an input buffer for a frame */ rgbBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 3); /* get the output 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); } while (fread(yBuf, 1, frameWidth * frameHeight, yuvFile)&&fread(uBuf, 1, frameWidth * frameHeight/4, yuvFile)&&fread(vBuf, 1, frameWidth * frameHeight/4, yuvFile)) { if(yuv2rgb(frameWidth, frameHeight, rgbBuf, yBuf, uBuf, vBuf)) { printf("error"); return 0; } fwrite(rgbBuf, 1, frameWidth * frameHeight*3, rgbFile); printf("\r...%d", ++videoFramesWritten); } printf("\n%u %ux%u video frames written\n", videoFramesWritten, frameWidth, frameHeight); if(yBuf) free(yBuf); if(uBuf) free(uBuf); if(vBuf) free(vBuf); if(rgbBuf) free(rgbBuf); if(rgbFile) fclose(rgbFile); if(yuvFile) fclose(yuvFile); return 0; }#include "stdlib.h" #include "yuv2rgb.h" static float RGBYUV14075[256], RGBYUV03455[256], RGBYUV07169[256],RGBYUV17790[256]; int yuv2rgb(int width, int height, void *rgb_out, void *y_in, void *u_in, void *v_in) { static int init_done = 0; long x, y, size; unsigned char *R, *G, *B; unsigned char *Y, *U, *V; unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv; unsigned char *y_buffer, *u_buffer, *v_buffer,*rgb_buffer; unsigned char *sub_u_buf, *sub_v_buf; if (init_done == 0) { InitLookupTable(); init_done = 1; } // check to see if width and height are divisible by 2 if ((width % 2) || (height % 2)) return 1; size = width * height; // allocate memory y_buffer = (unsigned char *)y_in; u_buffer = (unsigned char *)u_in; v_buffer = (unsigned char *)v_in; rgb_buffer = (unsigned char *)rgb_out; sub_u_buf = (unsigned char *)malloc(size); sub_v_buf = (unsigned char *)malloc(size); Y = y_buffer; U = sub_u_buf; V = sub_v_buf; B=rgb_buffer; // /上采样// for (y = 0; y 255) {*R=(unsigned char)255;} else if ((*Y + RGBYUV14075[*V])<0) {*R=(unsigned char)0;} else *R= (unsigned char)(*Y + RGBYUV14075[*V]); if((*Y - RGBYUV03455[*U] - RGBYUV07169[*V])>255) { *G=255;} else if((*Y - RGBYUV03455[*U] - RGBYUV07169[*V])<0) { *G=0;} else *G= (unsigned char)(*Y - RGBYUV03455[*U] - RGBYUV07169[*V]); if((*Y + RGBYUV17790[*U])>255) {*B=255;} else if((*Y + RGBYUV17790[*U])<0) {*B=0;} else *B= (unsigned char)(*Y + RGBYUV17790[*U]); B+=3; Y++; U++; V++; } } if(sub_u_buf) free(sub_u_buf); if(sub_v_buf) free(sub_v_buf); return 0; } void InitLookupTable() { int i; for (i = 0; i < 256; i++) RGBYUV14075[i] = (float)1.4075 * (i-128); for (i = 0; i < 256; i++) RGBYUV03455[i] = (float)0.3455 * (i-128); for (i = 0; i < 256; i++) RGBYUV07169[i] = (float)0.7169 * (i-128); for (i = 0; i < 256; i++) RGBYUV17790[i] = (float)1.7790 * (i-128); } 四.实验结果及分析 原始yuv文件为左图,此yuv经过yuv2rgb程序后生成的up.rgb再通过已有的rgb2yuv程序生成down.yuv文件。经过yuv->rgb->yuv格式转换的yuv图像如下右图。 可看出经过上采样与下采样处理后的图像较于原始图像略暗,但整体并没有太大差异 左:原始图像                                                                                                右:经变换处理后的图像

    转载请注明原文地址: https://ju.6miu.com/read-34177.html

    最新回复(0)