我想很多朋友在解码器输出时都会看到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拉。