本文转载自http://blog.csdn.net/lin453701006/article/details/78109934,在原作者的基础上修改了部分结构以及添加代码实现部分,在此对原作者表示感谢!

在360Lib对应的Software Manual中,定义了与HEVC客观质量评价PSNR不同的评价指标WS-PSNR,下文对这个指标进行分析。

WS-PSNR

参考提案:JVET-D0040,JVET-F1003 (http://phenix.int-evry.fr/jvet/)
WS-PSNR相较于PSNR的改进之处在于,它在计算块失真时考虑了块在当前图像中的纬度信息,原文是“Calculate PSNR based on all samples; the distortion is weighted by sample area on corresponding spherical surface”.
WS-PSNR对应的代码在项目Tlib360中的TWSPSNRMetricCalc.h和TWSPSNRMetricCalc.cpp中
先分析TWSPSNRMetricCalc.h
class TWSPSNRMetric
{
private:Bool      m_bEnabled;Double    m_dWSPSNR[3];Int       m_outputBitDepth[MAX_NUM_CHANNEL_TYPE];         ///< bit-depth of output fileInt       m_referenceBitDepth[MAX_NUM_CHANNEL_TYPE];      ///< bit-depth of reference file//各投影格式权重,Y:亮度权重,C:色度权重Double* m_fErpWeight_Y;Double* m_fErpWeight_C;Double* m_fCubeWeight_Y;Double* m_fCubeWeight_C;Double* m_fEapWeight_Y;Double* m_fEapWeight_C;Double* m_fOctaWeight_Y;Double* m_fOctaWeight_C;Double* m_fIcoWeight_Y;Double* m_fIcoWeight_C;
#if SVIDEO_WSPSNR_SSPDouble* m_fSspWeight_Y;Double* m_fSspWeight_C;
#endifInt     m_codingGeoType;      //编码几何类型Int     m_iCodingFaceWidth;       //编码面宽度Int     m_iCodingFaceHeight;      //编码面高度Int     m_iChromaSampleLocType;       //采样色度格式
#if SVIDEO_WSPSNR_E2E//for E2E WS-PSNR calculation;
#if !SVIDEO_E2E_METRICSTVideoIOYuv *m_pcTVideoIOYuvInputFile;  //note: reference;TGeometry   *m_pRefGeometry;TGeometry   *m_pRecGeometry;TComPicYuv  *m_pcOrgPicYuv;TComPicYuv  *m_pcRecPicYuv;             //in original geometry domain;
#endif
#if !SVIDEO_E2E_METRICSInt         m_iLastFrmPOC;UInt        m_temporalSubsampleRatio;Int         m_iInputWidth;Int         m_iInputHeight;ChromaFormat m_inputChromaFomat;
#endif
#endif
public:TWSPSNRMetric();virtual ~TWSPSNRMetric();Bool    getWSPSNREnabled()  { return m_bEnabled; }        //获取m_bEnabledVoid    setWSPSNREnabledFlag(Bool bEnabledFlag)  { m_bEnabled = bEnabledFlag; }       //设置m_bEnabledVoid    setOutputBitDepth(Int iOutputBitDepth[MAX_NUM_CHANNEL_TYPE]);     //输出图像bit深度Void    setReferenceBitDepth(Int iReferenceBitDepth[MAX_NUM_CHANNEL_TYPE]);       //参考图像bit深度//设置视频几何信息Void    setCodingGeoInfo(SVideoInfo& sVidInfo, Int iChromaSampleLocType) { m_codingGeoType = sVidInfo.geoType; m_iCodingFaceWidth = sVidInfo.iFaceWidth; m_iCodingFaceHeight = sVidInfo.iFaceHeight; m_iChromaSampleLocType =iChromaSampleLocType; }
#if SVIDEO_WSPSNR_E2E
#if SVIDEO_E2E_METRICSVoid    setCodingGeoInfo2(SVideoInfo& sRefVideoInfo, SVideoInfo& sRecVideoInfo, InputGeoParam *pInGeoParam);Void    xCalculateE2EWSPSNR(TComPicYuv *pcRecPicYuv, TComPicYuv *pcOrigPicYuv);
#elseVoid    setCodingGeoInfo2(SVideoInfo& sRefVideoInfo, SVideoInfo& sRecVideoInfo, InputGeoParam *pInGeoParam, TVideoIOYuv& yuvInputFile, Int iInputWidth, Int iInputHeight, UInt tempSubsampleRatio);Void    xCalculateE2EWSPSNR(TComPicYuv *pcPicD, Int iPOC);
#endif
#endifDouble* getWSPSNR() {return m_dWSPSNR;}       //获取WS-PSNRVoid    createTable(TComPicYuv* pcPicD, TGeometry *pcCodingGeomtry);      //创建投影格式对应的权重列表Void    xCalculateWSPSNR( TComPicYuv* pcOrgPicYuv, TComPicYuv* pcPicD );      //计算WS-PSNR//inline Int round(POSType t) { return (Int)(t+ (t>=0? 0.5 :-0.5)); };
};

再分析 TWSPSNRMetricCalc.cpp中的函数,这个cpp文件中除去构造、析构、以及setCodingGeoInfo2()外,只剩下如下两个函数。

void TWSPSNRMetric::createTable():创建投影格式对应的权重列表。这里只截取了最常用的ERP和CMP对应的部分。每一种投影格式都对应一种权重,可以看到ERP的权重只与高度位置相关,CMP的权重与所在面的x,y坐标位置相关。

void TWSPSNRMetric::createTable(TComPicYuv* pcPicD, TGeometry *pcCodingGeomtry)
{if(!m_bEnabled){return;}SVideoInfo *pCodingSVideoInfo = pcCodingGeomtry->getSVideoInfo();Int iFaceWidth = pCodingSVideoInfo->iFaceWidth;Int iFaceHeight = pCodingSVideoInfo->iFaceHeight;Int iScaleX = pcPicD->getComponentScaleX(COMPONENT_Cb);Int iScaleY = pcPicD->getComponentScaleY(COMPONENT_Cb);Double dChromaOffset[2] = {0.0, 0.0}; //[0: X; 1: Y];if(pcPicD->getChromaFormat() == CHROMA_420){dChromaOffset[0] = (m_iChromaSampleLocType == 0 || m_iChromaSampleLocType == 2)? 0 : 0.5;dChromaOffset[1] = (m_iChromaSampleLocType == 2 || m_iChromaSampleLocType == 3)? 0 : 0.5;}//ERP投影if(pcCodingGeomtry->getType()==SVIDEO_EQUIRECT){Double fWeightSum_Y=0;Double fWeightSum_C=0;Int   iWidth = pcPicD->getWidth(COMPONENT_Y) ;      //获取亮度宽度Int   iHeight = pcPicD->getHeight(COMPONENT_Y) ;    //获取亮度高度Int   iWidthC = pcPicD->getWidth(COMPONENT_Cb) ;        //获取色度宽度Int   iHeightC = pcPicD->getHeight(COMPONENT_Cb) ;  //获取色度高度m_fErpWeight_Y=(Double*)malloc(iHeight*sizeof(Double));     //亮度权重和高度有关m_fErpWeight_C=(Double*)malloc(iHeightC*sizeof(Double));        //色度权重和高度有关//计算亮度和色度的纬度权重for(Int y=0; y< iHeight; y++){m_fErpWeight_Y[y]=scos((y-(iHeight/2-0.5))*S_PI/iHeight); //F1003 公式(72),计算亮度权重fWeightSum_Y += m_fErpWeight_Y[y];}for(Int y=0; y< iHeightC; y++){m_fErpWeight_C[y]=scos(((y<<iScaleY)+dChromaOffset[1]+0.5-iHeight/2)*S_PI/iHeight);  //F1003 公式(72),计算色度权重fWeightSum_C += m_fErpWeight_C[y];}for(Int y=0; y< iHeight; y++){m_fErpWeight_Y[y]=m_fErpWeight_Y[y]/fWeightSum_Y/iWidth;}for(Int y=0; y< iHeightC; y++){m_fErpWeight_C[y]=m_fErpWeight_C[y]/fWeightSum_C/(iWidthC);}}//CMP投影else if(pcCodingGeomtry->getType()==SVIDEO_CUBEMAP){Double fWeightSum_Y=0;Double fWeightSum_C=0;    //亮度、色度权重和面的高度宽度都有关m_fCubeWeight_Y=(Double*)malloc(iFaceHeight * iFaceWidth*sizeof(Double));       m_fCubeWeight_C=(Double*)malloc((iFaceHeight >> iScaleY) * (iFaceWidth >> iScaleX)*sizeof(Double));//计算亮度和色度权重for(Int y = 0; y < iFaceHeight; y++ ){for(Int x=0; x < iFaceWidth; x++){Int ci, cj, r2;Double d2;ci= iFaceWidth/2;cj= iFaceHeight/2;d2 = (x+0.5-ci)*(x+0.5-ci)+(y+0.5-cj)*(y+0.5-cj);r2 = (iFaceWidth/2)*(iFaceWidth/2);Double weight= 1.0/((1+d2/r2)*ssqrt(1.0*(1+d2/r2)));m_fCubeWeight_Y[iFaceWidth*y+x] = weight;fWeightSum_Y += weight;}}for(Int y = 0; y < iFaceHeight; y++ ){for(Int x=0; x<iFaceWidth; x++){m_fCubeWeight_Y[iFaceHeight*y+x] = (m_fCubeWeight_Y[iFaceHeight*y+x])/fWeightSum_Y/6.0;}}for(Int y = 0; y < (iFaceHeight>>iScaleY); y++ ){for(Int x=0; x< (iFaceWidth>>iScaleX); x++){Int ci, cj, r2;Double d2;ci= iFaceWidth/2;cj= iFaceHeight/2;d2 = (x*(1<<iScaleX)+dChromaOffset[0]+0.5 - ci)*(x*(1<<iScaleX)+dChromaOffset[0]+0.5 - ci) + (y*(1<<iScaleY)+dChromaOffset[1]+0.5 -cj)*(y*(1<<iScaleY)+dChromaOffset[1]+0.5 -cj);r2 = (iFaceWidth/2)*(iFaceWidth/2);Double weight= 1.0/((1+d2/r2)*sqrt(1.0*(1+d2/r2)));m_fCubeWeight_C[(iFaceWidth>>iScaleX)*y+x]=weight;fWeightSum_C += weight;}}for(Int y = 0; y < (iFaceHeight>>iScaleY); y++ ){for(Int x=0; x< (iFaceWidth>>iScaleX); x++){m_fCubeWeight_C[(iFaceWidth>>iScaleX)*y+x]=(m_fCubeWeight_C[(iFaceWidth>>iScaleX)*y+x])/fWeightSum_C/6.0;}}}
}

Void TWSPSNRMetric::xCalculateWSPSNR()

Void TWSPSNRMetric::xCalculateWSPSNR( TComPicYuv* pcOrgPicYuv, TComPicYuv* pcPicD )
{//初始化亮度色度bit信息Int iBitDepthForPSNRCalc[MAX_NUM_CHANNEL_TYPE];Int iReferenceBitShift[MAX_NUM_CHANNEL_TYPE];Int iOutputBitShift[MAX_NUM_CHANNEL_TYPE];iBitDepthForPSNRCalc[CHANNEL_TYPE_LUMA] = std::max(m_outputBitDepth[CHANNEL_TYPE_LUMA], m_referenceBitDepth[CHANNEL_TYPE_LUMA]);iBitDepthForPSNRCalc[CHANNEL_TYPE_CHROMA] = std::max(m_outputBitDepth[CHANNEL_TYPE_CHROMA], m_referenceBitDepth[CHANNEL_TYPE_CHROMA]);iReferenceBitShift[CHANNEL_TYPE_LUMA] = iBitDepthForPSNRCalc[CHANNEL_TYPE_LUMA] - m_referenceBitDepth[CHANNEL_TYPE_LUMA];iReferenceBitShift[CHANNEL_TYPE_CHROMA] = iBitDepthForPSNRCalc[CHANNEL_TYPE_CHROMA] - m_referenceBitDepth[CHANNEL_TYPE_CHROMA];iOutputBitShift[CHANNEL_TYPE_LUMA] = iBitDepthForPSNRCalc[CHANNEL_TYPE_LUMA] - m_outputBitDepth[CHANNEL_TYPE_LUMA];iOutputBitShift[CHANNEL_TYPE_CHROMA] = iBitDepthForPSNRCalc[CHANNEL_TYPE_CHROMA] - m_outputBitDepth[CHANNEL_TYPE_CHROMA];memset(m_dWSPSNR, 0, sizeof(Double)*3);TComPicYuv &picd=*pcPicD;//Double SSDspsnr[3]={0, 0 ,0};//ChromaFormat chromaFormat = pcPicD->getChromaFormat();for(Int chan=0; chan<pcPicD->getNumberValidComponents(); chan++){const ComponentID ch=ComponentID(chan);const Pel*  pOrg       = pcOrgPicYuv->getAddr(ch);const Int   iOrgStride = pcOrgPicYuv->getStride(ch);const Pel*  pRec       = picd.getAddr(ch);const Int   iRecStride = picd.getStride(ch);const Int   iWidth  = pcPicD->getWidth (ch) ;const Int   iHeight = pcPicD->getHeight(ch) ;Double fWeight =1;Double fWeightSum=0;//Int   iSize   = iWidth*iHeight;Double SSDwpsnr=0;//WS-PSNRfor(Int y = 0; y < iHeight; y++ )   //得到宽高后,对每一个点的失真进行统计{//ERP格式只与高度有关if (m_codingGeoType==SVIDEO_EQUIRECT){      if(!chan)   //亮度{fWeight=m_fErpWeight_Y[y];}else        //色度{fWeight=m_fErpWeight_C[y];}}for(Int x = 0; x < iWidth; x++ ) {//参考图像和输出图像差值Intermediate_Int iDiff = (Intermediate_Int)( (pOrg[x]<<iReferenceBitShift[toChannelType(ch)]) - (pRec[x]<<iOutputBitShift[toChannelType(ch)]) );//CMP格式和x,y都有关if (m_codingGeoType==SVIDEO_CUBEMAP){if(!chan){if(iWidth/4 == iHeight/3 && x >= iWidth/4 && (y< iHeight/3 || y>= 2*iHeight/3)){fWeight=0;}else {fWeight=m_fCubeWeight_Y[(m_iCodingFaceWidth)*(y%(m_iCodingFaceHeight)) +(x%(m_iCodingFaceWidth))];}}else{if(iWidth/4 == iHeight/3 && x >= iWidth/4 && (y< iHeight/3 || y>= 2*iHeight/3)){fWeight=0;}else{fWeight=m_fCubeWeight_C[(m_iCodingFaceWidth>>(pcPicD->getComponentScaleX(COMPONENT_Cb)))*(y%(m_iCodingFaceHeight>>(pcPicD->getComponentScaleY(COMPONENT_Cb)))) +(x%(m_iCodingFaceWidth>>(pcPicD->getComponentScaleX(COMPONENT_Cb))))];}  }}if(fWeight>0)fWeightSum += fWeight;SSDwpsnr   += iDiff * iDiff*fWeight;        //引入了fWeight,即对每个点的失真进行一个权重处理。最终得到总的SSD}pOrg += iOrgStride;pRec += iRecStride;}const Int maxval = 255<<(iBitDepthForPSNRCalc[toChannelType(ch)]-8) ;//const Double fRefValue = (Double) maxval * maxval * iSize;m_dWSPSNR[ch]         = ( SSDwpsnr ? 10.0 * log10( (maxval * maxval*fWeightSum) / (Double)SSDwpsnr ) : 999.99 );        //计算PSNR}}

360视频质量评估标准:WS-PSNR及对应代码实现部分相关推荐

  1. 全参考客观视频质量评价方法 (MSE, PSNR,SSIM)原理

    全参考客观视频质量评价方法是指把原始参考视频与失真视频在每一个对应帧中的每一个对应像素之问进行比较.准确的讲,这种方法得到的并不是真正的视频质量,而是失真视频相对于原始视频的相似程度或保真程度.最简单 ...

  2. 全参考视频质量评价方法(PSNR,SSIM)以及相关数据库

    最常用的全参考视频质量评价方法有以下2种: PSNR(峰值信噪比):用得最多,但是其值不能很好地反映人眼主观感受.一般取值范围:20-40.值越大,视频质量越好. SSIM(结构相似性):计算稍复杂, ...

  3. 视频质量评价PSNR

    PSNR(Peak Signal to Noise Ratio,峰值信噪比)是最基础的视频质量评价方法.它的取值一般在20-50之间,值越大代表受损图片越接近原图片.PSNR通过对原始图像和失真图像进 ...

  4. 音视频技术:视频质量评价方法简介

    视频质量评估(VQA)一直是个很活跃的研究领域,原因其一是业内一直缺少一种统一且准确的评估标准,其二是影响视频质量的因素过多,且包含很多主观因素,难以客观.定量地评价.经过这么多年的研究,已经诞生了非 ...

  5. 音视频技术:视频质量评价方法简介 1

    视频质量评估(VQA)一直是个很活跃的研究领域,原因其一是业内一直缺少一种统一且准确的评估标准,其二是影响视频质量的因素过多,且包含很多主观因素,难以客观.定量地评价.经过这么多年的研究,已经诞生了非 ...

  6. 视频质量评价方法简介

    周鑫 2017年毕业于浙江大学,读研期间主要进行视频编码相关研究,目前在通信与视频部门进行转码引擎相关研发. 作者简介 ●●● 引言 视频质量评估(VQA)一直是个很活跃的研究领域,原因其一是业内一直 ...

  7. 基于编码应用的主观全景视频质量评价数据库(译)

    subjective panoramic video quality assessment database for coding applications IEEE TRANSACTIONS ON ...

  8. [总结]视频质量评价技术零基础学习方法

    前段时间略忙,因此一直计划要总结的很多东西都没来得及写,这两天趁着空闲时间写上一篇.以后等时间充裕了再补充一些内容.本文总结一下学习视频质量评价技术的方法.视频质量评价是我研究生阶段主要的工作,包括发 ...

  9. [论文阅读](图像/视频质量评价系列)

    文章目录 [2021] (QoMEX) Image Super-Resolution Quality Assessment:Structural Fidelity Versus Statistical ...

最新文章

  1. (附视频) | AI奠基人、美国AI科学家特伦斯谈深度学习​
  2. (转载)机器学习知识点(十三)吉布斯采样法(Gibbs Sampling)
  3. 从计算机知识到落地能力,你欠缺了什么?
  4. Win7系统不能录音怎么办
  5. 【LOJ101】最大流(Edmonds-Karp)
  6. 阿里开源 10 年,这封信里也有 Flink 的身影。
  7. jdk API说明手册
  8. 软考初级程序员---题目(二)
  9. opencv 图像阈值 二值化处理
  10. 开源项目Smail动工
  11. 如何在国外做好自然科学研究-2
  12. 前端人脸识别框架tracking.js,解决ios浏览器调摄像头黑屏的问题,兼容pc、安卓、ios。
  13. 405 Method Not Allowed 解决方案
  14. Nvidia显卡官方驱动下载地址
  15. Win10笔记本电脑某些应用能使用麦克风,但某些无法使用麦克风解决方法(本文以QQ为例,其他应用也适用)
  16. 【iOS】iPhone4 无SHSH备份如何降级至6.1.2版本?
  17. MISRA-C 2004 规则解读(41S-60S)
  18. noip day2 聪明的质检员
  19. can报文信号矩阵分析
  20. python资源管理器 计算机项目下的_高级语言程序设计(Python)_中国大学MOOC(慕课)_题库及答案...

热门文章

  1. Suricata配置文件说明1
  2. 考研英语写作素材:常用特色词汇
  3. java遍历jsonobject_Java遍历JsonObject对象代码示例
  4. template的用法(超详细)
  5. python数字推盘游戏怎么显示步数_用 Python 修改微信(支付宝)运动步数,轻松 TOP1...
  6. 【华为OD机试 2023最新 】 密室逃生游戏(C++ 100%)
  7. 如何卸载电脑上的某个软件或程序?
  8. [QCTF2018]picture
  9. 华为emui10鸿蒙,不亚于华为鸿蒙OS的EMUI10.0,到底带来了哪些惊喜?
  10. BZOJ5217: [Lydsy2017省队十连测]航海舰队