您的位置:首页 > 其它

数据压缩实验一实验报告

2017-03-08 20:43 465 查看

数据压缩实验一实验报告

1.实验原理

YUV到RGB的转换算法为

R=Y+1.4075(V−128)

G=Y+0.3455(U−128)−0.7169(V−128)

B=Y+1.779(U−128)

分析

此时的U、V实际上是Cb和Cr,为把(R-Y)和(B-Y)的动态范围控制在±350mV内,引入压缩系数,可以得到公式

Cr=0.713(R-Y)

Cb=0.564(B-Y)

又为了便于数字化处理,还要将Cr、Cb引入350mV的偏置,又由于经过8比特量化,色差信号经过归一化处理后,动态范围为-0.5-0.5,让色差零电平对应码电平128。所以公式变为

V=0.713(R-Y)+128

U=0.564(B-Y)+128

经过方程式的计算,可以得到最后的公式

RGB和YUV彩色空间基本原理

RGB彩色空间存储方式是每一个像素点都按照B、G、R的顺序进行存储,每一帧占用空间为width * height * 3个字节的空间。YUV彩色空间存储方式为每一帧的YUV分开存储,每一帧Y占用的空间为width * height,每一帧U和V所占用的空间分别为width * height /4。

取样格式

读取的图片为YUV空间,取样格式为4:2:0,即V和U的水平和垂直采样点数均为Y的一半。但要生成的RGB文件的取样格式为4:4:4,这就要求我们对给定的Y保持不变,对给定的U和V进行上采样,使其可与RGB的采样空间相同。 根据将RGB转成YUV的实验中下采样的方法,我采用的方法是用指针指向yuv文件中的u、v,并开辟两个128*128的空间存*储文件中的u、v。同时还开辟了两个256*256的空间,将一个指向给定uv指针的内容赋值给新的四个像素块,详见具体代码。

2.实验的流程分析

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

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

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

写RGB文件

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

命令行参数的设置

project->properties->Debugging->

Working Directory&Command Arguments



3.重要代码及分析

重要代码通过高亮标出

yuv转为rgb的函数代码:yuv2rgb.cpp

#include "stdlib.h"
#include "yuv2rgb.h"

static float RGBYUV14075[256], RGBYUV03455[256];
static float RGBYUV07169[256], RGBYUV17790[256];

int YUV2RGB(int x_dim, int y_dim, void *bmp, void *y_in, void *u_in, void *v_in, int flip)
{
static int init_done = 0;

long i, j, 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;
unsigned char *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
if ((x_dim % 2) || (y_dim % 2)) return 1;
size = x_dim * y_dim;

// allocate memory
y_buffer = (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;
g = b + 1;
r = b + 2;
y = y_buffer;
u = u_buffer;
v = v_buffer;


for (j = 0; j < y_dim / 2; j++)
{
psu = sub_u_buf + j * x_dim / 2;//128*128
psv = sub_v_buf + j * x_dim / 2;
pu1 = 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++)
{
*pu1 = *psu;
*(pu1 + 1) = *psu;
*pu2 = *psu;
*(pu2 + 1) = *psu;
*pv1 = *psv;
*(pv1 + 1) = *psv;
*pv2 = *psv;
*(pv2 + 1) = *psv;
psu++;
psv++;
pu1 += 2;
pu2 += 2;
pv1 += 2;
pv2 += 2;
/*为了将yuv的取样空间由4:2:0变为4:4:4,就要将一个像素块的值赋给四个像素,psu指针指向的是输入的u的空间,将psu指针指向的一个值赋给新开辟空间中的四个像素,比如将psu指向的第一个值赋给第一行的第一、二个值,即pu1和pu1+1及第二行中的第一二个值pu2和pu2+1。然后psv指针指向的是输入的v的空间。*/
}
}


for (i = 0; i < size; i++)
{

g = b + 1;
r = b + 2;
float tmp;
/*r的数据类型为unsigned char,范围为0~255,如果直接进行计算则会出现溢出现象,比如计算得出256,则会变为0,因此通过设置浮点型中间变量tmp防止数据的溢出*/
tmp= (*y + RGBYUV14075[*v]);
if (tmp > 255) { tmp = 255; }
if (tmp < 0) { tmp = 0; }
*r = (unsigned char)tmp;
tmp = (*y - RGBYUV03455[*u] - RGBYUV07169[*v]);
if (tmp > 255) { tmp = 255; }
if (tmp < 0) { tmp = 0; }
*g = (unsigned char)tmp;
tmp = (*y + RGBYUV17790[*u]);
if (tmp > 255) { tmp = 255; }
if (tmp < 0) { tmp = 0; }
*b = (unsigned char) tmp;
b += 3;
y++;
u++;
v++;

}
return 0;
}


/*采用部分查找表法,提高运行效率*/
void InitLookupTable()
{
int i;
for (i = 0; i < 256; i++) RGBYUV14075[i] = (float)1.0475 * (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.779 * (i-128);
}


主函数

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#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;
bool flip =TRUE;
//unsigned int i;

/* internal variables */
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;

/* begin process command line */
/* point to the specified file names */
yuvFileName = argv[1];
rgbFileName = argv[2];

frameWidth = atoi(argv[3]);
frameHeight = atoi(argv[4]);


/* 打开yuv文件*/
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);

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, flip))
{
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(rgbBuf!=NULL){free(rgbBuf);}
if(yBuf!=NULL){free(yBuf);}
if(uBuf!=NULL){free(uBuf);}
if(vBuf!=NULL){free(vBuf);}
if(yuvFile!=NULL){fclose(yuvFile);}
if(rgbFile!=NULL){fclose(rgbFile);}
return (0);


}

4.实验结果及分析

错误及调试

1.程序build后没有报错,但在运行过程中出现了breakpoint,经过F11进入main函数,F10进行分步运行后,在main函数中发现错误,释放空间时多次释放rgb空间,而没有释放y、u、v的空间。

2.程序运行后,出现的测试yuv图像所有像素的yuv值均相同,通过检查,发现是yuv指针都始终指向第一个像素点,指针没有移动,后来通过y++,u++,v++的语句移动指针。



3.没有设置tmp为中间变量时出现少量溢出错误,在最终呈现的test。yuv图像上出现蓝色的小色块。以下是对比图。 生成的test图像:



最后结果



2.





内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: