1、生成YUV420p格式的灰阶测试图
灰阶代表了由最暗到最亮之间不同亮度的层次级。这中间层级越多,所能够呈现的画面效果也就越细腻。
// 生成灰阶测试图, barnum指有多少个亮度层次
void yuv420_graybar(int w, int h, int ymin, int ymax, int barnum) {
FILE *fout = fopen("output_graybar.yuv", "w+");
unsigned char data_y[w*h];
unsigned char data_u[w*h/4];
unsigned char data_v[w*h/4];
unsigned char lums[barnum]; //亮度
float lum_inc = (float)(ymax - ymin) / (barnum - 1);
for (int i = 0; i < barnum; i++) {
lums[i] = ymin + (unsigned char)(i * lum_inc);
}
unsigned char level[w];
int barwidth = w / barnum;
for (int i = 0; i < barnum; i++) {
memset(level + i*barwidth, lums[i], barwidth);
}
// draw picture
for (int i = 0; i < h; i++) {
memcpy(data_y + i*w, level, w);
}
memset(data_u, 128, w*h/4);
memset(data_v, 128, w*h/4);
fwrite(data_y, w*h, 1, fout);
fwrite(data_u, w*h/4, 1, fout);
fwrite(data_v, w*h/4, 1, fout);
fclose(fout);
}
函数调用:yuv420_graybar(320, 240, 0, 255, 10);
2、评估图像受损程度
PSNR是最基本的视频质量评价方法。通过计算受损图像和原始图像之间的差别,评价受损图像的质量。PSNR取值通常情况下都在20-50的范围内,取值越高,代表两张图像越接近,图像受损程度低。
①
M
S
E
=
1
w
∗
h
∑
i
=
1
w
∑
j
=
1
h
(
x
i
j
−
y
i
j
)
2
①MSE = \frac{1}{w*h}\sum_{i=1}^w\sum_{j=1}^h(x_{ij} - y_{ij})^2
①MSE=w∗h1i=1∑wj=1∑h(xij−yij)2
②
P
S
N
R
=
10
∗
l
o
g
10
(
25
5
2
M
S
E
)
②PSNR = 10*log_{10}(\frac{255^2}{MSE})
②PSNR=10∗log10(MSE2552)
注:w、h分别是图像的宽高,xij和yij分别是两张图像的每一个像素值。
①先获得一张受损图像(修改Y分量):
②对比两张图像的Y分量
void yuv420_psnr(char *origin, char *target, int w, int h, int num) {
FILE *fp = fopen(origin, "r");
FILE *ft = fopen(target, "r");
unsigned char buf1[w*h];
unsigned char buf2[w*h];
float psnr = 0.0;
for (int i = 0; i < num; i++) {
fread(buf1, 1, w*h, fp);
fread(buf2, 1, w*h, ft);
int sum = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
int t = i*w + j;
sum += pow((buf1[t] - buf2[t]),2);
}
}
float MSE = (float)sum / (float)(w*h);
psnr = 10*log10(255*255/MSE);
printf("psnr: %f\n", psnr);
fseek(fp, w*h/2, SEEK_CUR);
fseek(ft, w*h/2, SEEK_CUR);
}
fclose(fp);
fclose(ft);
}
函数调用:yuv420_psnr("origin.yuv", "target.yuv", 640, 272, 1);
编译链接:gcc yuv420_psnr.c -lm
运行结果:psnr: 23.300215