转:解码器输出PSNR为0表示什么
我想很多朋友在解码器输出时都会看到PSNR等于0的情况,这代表了什么意思呢?这表示你解码得到的图像和参考图像是一致的。下面基于baseline的情况详细说明一下。
首先看ldecod.c中的main()函数
init_conf(input, argv[1]);
…
img->idr_psnr_number=input->ref_offset;
显然这边的init_conf()是从decoder.cfg配置文件中读取数据,并且input->ref_offset对应的是配置文件中的SNR computation offset的值,在默认的情况下,JM8.6设置为0。
接着看image.c中的find_snr()函数,这就是用来计算PSNR数值的。
if (psnrPOC==0 && img->psnr_number)
img->idr_psnr_number=img->psnr_number + 1;
img->psnr_number=max(img->psnr_number,img->idr_psnr_number+psnrPOC);
frame_no = img->idr_psnr_number+psnrPOC;
这边计算出了frame_no的值,这个变量代表了什么含义,个人认为,应该是表示当前解码图像的参考图像(这个参考图像并不是指ListX中的,而是指参考序列中的)序号,为什么这么认为,请看下面。
rewind(p_ref);//使文件的位置指针重新返回文件的开头
for (i=0; i<frame_no; i++)
{
status = fseek (p_ref, (long) p->size_y* (long) (p->size_x*3/2), SEEK_CUR);
if (status != 0)
{
snprintf(errortext, ET_SIZE, "Error in seeking frame number: %d", frame_no);
fprintf(stderr, "%s", errortext);
return;
}
}
这段代码什么含义呢,很清楚,看下面的图。
接着看下面的求亮度PSNR的代码,色度的类似。
for (j=0; j < p->size_y; j++)
for (i=0; i < p->size_x; i++)
imgY_ref[j][i]=fgetc(p_ref);
//以frame_no=3的情况,那么此时imgY_ref就是得到了Ref3的亮度数据
…
img->quad[0]=0;
diff_y=0;
for (j=0; j < p->size_y; ++j)
{
for (i=0; i < p->size_x; ++i)
{
diff_y += img->quad[abs(p->imgY[j][i]-imgY_ref[j][i])];
}
}
//比较参考图像和解码图像并求得SAD
…
if (diff_y != 0)
snr->snr_y=(float)(10*log10(65025*(float)(p->size_x)*(p->size_y)/(float)diff_y));
else
snr->snr_y=0;
//如果前面的diff_y等于0,那么PSNR就是0,反之,按公式求
分析了这么多,可能大家还是不明白原因,那么我想说,一切根源其实就在decoder.cfg配置文件中SNR computation offset的值的选取,如果取默认的0,那么在求diff_y的时候,就是计算当前解码图像和对应序号的参考图像差值,如果取1,那么就是计算当前解码图像和后一序号的参考图像的差值,以此类推。因此我们不难看出,当SNR computation offset的值为0,且解码图像没有误码的情况,跟它序号相同的参考图像比较的diff_y肯定是0,相应的,根据上面的代码,那么最后求得的PSNR肯定也是0拉。