HEVC学习之琐事(四):如何计算PSNR

简介: <p>在HEVC官方参考软件HM中,计算PSNR的代码如下,当然还有很多工具计算PSNR。</p> <p>现在提供一种很方便的工具,只需给出原始YUV文件和解码或重构后的YUV文件就可以计算出其PSNR。软件下载地址为:<a target="_blank" href="http://download.csdn.net/detail/frd2009041510/8240547">点击打开链

在HEVC官方参考软件HM中,计算PSNR的代码如下,当然还有很多工具计算PSNR。

现在提供一种很方便的工具,只需给出原始YUV文件和解码或重构后的YUV文件就可以计算出其PSNR。软件下载地址为:点击打开链接

为了验证其正确性,本人测试了一下,结果如下图所示。

下图是HM得出的结果:


下图是该软件测出的结果:


结果一致。


Void TEncGOP::xCalculateAddPSNR( TComPic* pcPic, TComPicYuv* pcPicD, const AccessUnit& accessUnit, Double dEncTime )
{
  Int     x, y;
  UInt64 uiSSDY  = 0;
  UInt64 uiSSDU  = 0;
  UInt64 uiSSDV  = 0;
  
  Double  dYPSNR  = 0.0;
  Double  dUPSNR  = 0.0;
  Double  dVPSNR  = 0.0;
  
  //===== calculate PSNR =====
  Pel*  pOrg    = pcPic ->getPicYuvOrg()->getLumaAddr();
  Pel*  pRec    = pcPicD->getLumaAddr();
  Int   iStride = pcPicD->getStride();
  
  Int   iWidth;
  Int   iHeight;
  
  iWidth  = pcPicD->getWidth () - m_pcEncTop->getPad(0);
  iHeight = pcPicD->getHeight() - m_pcEncTop->getPad(1);
  
  Int   iSize   = iWidth*iHeight;
  
  for( y = 0; y < iHeight; y++ )
  {
    for( x = 0; x < iWidth; x++ )
    {
      Int iDiff = (Int)( pOrg[x] - pRec[x] );
      uiSSDY   += iDiff * iDiff;
    }
    pOrg += iStride;
    pRec += iStride;
  }
  
  iHeight >>= 1;
  iWidth  >>= 1;
  iStride >>= 1;
  pOrg  = pcPic ->getPicYuvOrg()->getCbAddr();
  pRec  = pcPicD->getCbAddr();
  
  for( y = 0; y < iHeight; y++ )
  {
    for( x = 0; x < iWidth; x++ )
    {
      Int iDiff = (Int)( pOrg[x] - pRec[x] );
      uiSSDU   += iDiff * iDiff;
    }
    pOrg += iStride;
    pRec += iStride;
  }
  
  pOrg  = pcPic ->getPicYuvOrg()->getCrAddr();
  pRec  = pcPicD->getCrAddr();
  
  for( y = 0; y < iHeight; y++ )
  {
    for( x = 0; x < iWidth; x++ )
    {
      Int iDiff = (Int)( pOrg[x] - pRec[x] );
      uiSSDV   += iDiff * iDiff;
    }
    pOrg += iStride;
    pRec += iStride;
  }
  
  Int maxvalY = 255 << (g_bitDepthY-8);
  Int maxvalC = 255 << (g_bitDepthC-8);
  Double fRefValueY = (Double) maxvalY * maxvalY * iSize;
  Double fRefValueC = (Double) maxvalC * maxvalC * iSize / 4.0;
  dYPSNR            = ( uiSSDY ? 10.0 * log10( fRefValueY / (Double)uiSSDY ) : 99.99 );
  dUPSNR            = ( uiSSDU ? 10.0 * log10( fRefValueC / (Double)uiSSDU ) : 99.99 );
  dVPSNR            = ( uiSSDV ? 10.0 * log10( fRefValueC / (Double)uiSSDV ) : 99.99 );

  /* calculate the size of the access unit, excluding:
   *  - any AnnexB contributions (start_code_prefix, zero_byte, etc.,)
   *  - SEI NAL units
   */
  UInt numRBSPBytes = 0;
  for (AccessUnit::const_iterator it = accessUnit.begin(); it != accessUnit.end(); it++)
  {
    UInt numRBSPBytes_nal = UInt((*it)->m_nalUnitData.str().size());
#if VERBOSE_RATE
    printf("*** %6s numBytesInNALunit: %u\n", nalUnitTypeToString((*it)->m_nalUnitType), numRBSPBytes_nal);
#endif
    if ((*it)->m_nalUnitType != NAL_UNIT_PREFIX_SEI && (*it)->m_nalUnitType != NAL_UNIT_SUFFIX_SEI)
    {
      numRBSPBytes += numRBSPBytes_nal;
    }
  }

  UInt uibits = numRBSPBytes * 8;
  m_vRVM_RP.push_back( uibits );

  //===== add PSNR =====
  m_gcAnalyzeAll.addResult (dYPSNR, dUPSNR, dVPSNR, (Double)uibits);
  TComSlice*  pcSlice = pcPic->getSlice(0);
  if (pcSlice->isIntra())
  {
    m_gcAnalyzeI.addResult (dYPSNR, dUPSNR, dVPSNR, (Double)uibits);
  }
  if (pcSlice->isInterP())
  {
    m_gcAnalyzeP.addResult (dYPSNR, dUPSNR, dVPSNR, (Double)uibits);
  }
  if (pcSlice->isInterB())
  {
    m_gcAnalyzeB.addResult (dYPSNR, dUPSNR, dVPSNR, (Double)uibits);
  }

  Char c = (pcSlice->isIntra() ? 'I' : pcSlice->isInterP() ? 'P' : 'B');
  if (!pcSlice->isReferenced()) c += 32;

#if ADAPTIVE_QP_SELECTION
  printf("POC %4d TId: %1d ( %c-SLICE, nQP %d QP %d ) %10d bits",
         pcSlice->getPOC(),
         pcSlice->getTLayer(),
         c,
         pcSlice->getSliceQpBase(),
         pcSlice->getSliceQp(),
         uibits );
#else
  printf("POC %4d TId: %1d ( %c-SLICE, QP %d ) %10d bits",
         pcSlice->getPOC()-pcSlice->getLastIDR(),
         pcSlice->getTLayer(),
         c,
         pcSlice->getSliceQp(),
         uibits );
#endif

  printf(" [Y %6.4lf dB    U %6.4lf dB    V %6.4lf dB]", dYPSNR, dUPSNR, dVPSNR );
  printf(" [ET %5.0f ]", dEncTime );
  
  for (Int iRefList = 0; iRefList < 2; iRefList++)
  {
    printf(" [L%d ", iRefList);
    for (Int iRefIndex = 0; iRefIndex < pcSlice->getNumRefIdx(RefPicList(iRefList)); iRefIndex++)
    {
      printf ("%d ", pcSlice->getRefPOC(RefPicList(iRefList), iRefIndex)-pcSlice->getLastIDR());
    }
    printf("]");
  }
}





目录
相关文章
|
7月前
|
传感器 编解码 人工智能
GEE数据集——MOD13A1.006Terra星搭载的中分辨率成像光谱仪获取的L3级植被指数产品
GEE数据集——MOD13A1.006Terra星搭载的中分辨率成像光谱仪获取的L3级植被指数产品
109 2
|
机器学习/深度学习 存储 文件存储
快到起飞 | PP-LCNet在CPU上让模型起飞,精度提升且比MobileNetV3+快3倍
快到起飞 | PP-LCNet在CPU上让模型起飞,精度提升且比MobileNetV3+快3倍
286 0
|
机器学习/深度学习
神经辐射场基于点,训练速度提升30倍,渲染质量超过NeRF
神经辐射场基于点,训练速度提升30倍,渲染质量超过NeRF
259 0
|
机器学习/深度学习 设计模式
卷积越大性能越强!RepLKNet一作在线分享:Transformer阴影下的超大卷积核复兴
卷积越大性能越强!RepLKNet一作在线分享:Transformer阴影下的超大卷积核复兴
104 0
|
机器学习/深度学习 存储 并行计算
神经辐射场去掉「神经」,训练速度提升100多倍,3D效果质量不减
神经辐射场去掉「神经」,训练速度提升100多倍,3D效果质量不减
163 0
|
编解码 Java BI
高精度10m/30米NPP净初级生产力分布数据
高精度10m/30米NPP净初级生产力分布数据
高精度10m/30米NPP净初级生产力分布数据
|
编解码 数据可视化 定位技术
Google Earth Engine——全球土壤体积密度数据集在6个标准深度(0、10、30、60、100和200厘米)的土壤体积密度(细土)10 x kg / m3,分辨率250米。
Google Earth Engine——全球土壤体积密度数据集在6个标准深度(0、10、30、60、100和200厘米)的土壤体积密度(细土)10 x kg / m3,分辨率250米。
161 0
Google Earth Engine——全球土壤体积密度数据集在6个标准深度(0、10、30、60、100和200厘米)的土壤体积密度(细土)10 x kg / m3,分辨率250米。
|
机器学习/深度学习 存储 并行计算
神经辐射场去掉「神经」,训练速度提升100多倍,3D效果质量不减
神经辐射场去掉「神经」,训练速度提升100多倍,3D效果质量不减
417 0
神经辐射场去掉「神经」,训练速度提升100多倍,3D效果质量不减
|
算法
《数字视频和高清:算法和接口》一1.4.1量化
本节书摘来华章计算机《数字视频和高清:算法和接口》一书中的第1章 ,第1.4.1节, [加]查尔斯·波因顿(Charles Poynton)著 刘开华 褚晶辉 马永涛 吕卫 宫霄霖 等译 译更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1019 0