VTM中YUV-PSNR的计算

2023-10-26

名词解释

参见文章cnblogs-什么是SAD,SAE,SATD,SSD,SSE,MAD,MAE,MSD,MSE?

PSNR的计算

较为标准的MSE计算公式和PSNR计算公式如下:
在这里插入图片描述
引用链接:CSDN-图像的峰值信噪比(PSNR)的计算方法
这里需要注意的是,PSNR的计算公式中,应该使用的是MAX(更标准),而不是常见的255,因为255是针对8bit的数据。
对于10bit的数据,不同的工具可能有不同的计算方式,大概在 2 10 − 1 2^{10}-1 2101附近。
VTM中maxval的计算方式如下:

const uint32_t maxval                = /*useWPSNR ? (1 << maximumBitDepth) - 1 :*/ 255 << (maximumBitDepth - 8); 
// fix with WPSNR: 1023 (4095) instead of 1020 (4080) for bit depth 10 (12)

对应的10bit是 255 ∗ 4 = 1020 255*4=1020 2554=1020
对应的12bit是 255 ∗ 16 = = 4080 255*16==4080 25516==4080

YUV-PSRN的计算

VTM中YUV-PSNR的计算并不是三个分量通过加权计算得到的,而是对各个分量的MSE进行加权计算得到的,进而计算得到YUV-PSNR。具体的权重计算分析见代码注释

void calculateCombinedValues(const ChromaFormat chFmt, double &PSNRyuv, double &MSEyuv, const BitDepths &bitDepths)
  {
    MSEyuv    = 0;
    int scale = 0;
	//计算maximumBitDepth
    int maximumBitDepth = bitDepths.recon[CHANNEL_TYPE_LUMA];
    for (uint32_t channelTypeIndex = 1; channelTypeIndex < MAX_NUM_CHANNEL_TYPE; channelTypeIndex++)
    {
      if (bitDepths.recon[channelTypeIndex] > maximumBitDepth)
      {
        maximumBitDepth = bitDepths.recon[channelTypeIndex];
      }
    }
//计算maxval
#if ENABLE_QPA
    const uint32_t maxval                = /*useWPSNR ? (1 << maximumBitDepth) - 1 :*/ 255 << (maximumBitDepth - 8); // fix with WPSNR: 1023 (4095) instead of 1020 (4080) for bit depth 10 (12)
#else
    const uint32_t maxval                = 255 << (maximumBitDepth - 8);
#endif
	//计算分量数
    const uint32_t numberValidComponents = getNumberValidComponents(chFmt);
	
	//遍历各个分量,计算对应的MSE
    for (uint32_t comp=0; comp<numberValidComponents; comp++)
    {
      const ComponentID compID        = ComponentID(comp);
      //下面会对函数getComponentScaleX部分单独
      const uint32_t        csx           = getComponentScaleX(compID, chFmt);
      const uint32_t        csy           = getComponentScaleY(compID, chFmt);
      const int         scaleChan     = (4>>(csx+csy));	//权重的计算
      //注意8bit和10bit的计算方式不同
      const uint32_t        bitDepthShift = 2 * (maximumBitDepth - bitDepths.recon[toChannelType(compID)]); //*2 because this is a squared number

	  //计算分量对应的MSE
      const double      channelMSE    = (m_MSEyuvframe[compID] * double(1 << bitDepthShift)) / double(getNumPic());
	 //累加权重
      scale  += scaleChan;
      //加权
      MSEyuv += scaleChan * channelMSE;
    }
	//平均
    MSEyuv /= double(scale);  // i.e. divide by 6 for 4:2:0, 8 for 4:2:2 etc.
    //计算YUV
    PSNRyuv = (MSEyuv == 0) ? 999.99 : 10.0 * log10((maxval * maxval) / MSEyuv);
  }

对于权重的计算函数,参见:

static inline uint32_t        getComponentScaleX        (const ComponentID id, const ChromaFormat fmt) { return getChannelTypeScaleX(toChannelType(id), fmt);               }
static inline uint32_t        getComponentScaleY        (const ComponentID id, const ChromaFormat fmt) { return getChannelTypeScaleY(toChannelType(id), fmt);               }

深入调用

static inline uint32_t        getChannelTypeScaleX      (const ChannelType id, const ChromaFormat fmt) { return (isLuma(id) || (fmt==CHROMA_444)) ? 0 : 1;                  }
static inline uint32_t        getChannelTypeScaleY      (const ChannelType id, const ChromaFormat fmt) { return (isLuma(id) || (fmt!=CHROMA_420)) ? 0 : 1;   

计算流程

SSD -> MSE -> PSNR
MSE的计算代码实现:

const uint32_t size   = width * height;

MSEyuvframe[comp] = (double)uiSSDtemp / size;

SSD的计算代码实现

const uint64_t uiSSDtemp = xFindDistortionPlane(recPB, orgPB, useWPSNR ? bitDepth : 0, ::getComponentScaleX(compID, format), ::getComponentScaleY(compID, format));

uint64_t EncGOP::xFindDistortionPlane(const CPelBuf& pic0, const CPelBuf& pic1, const uint32_t rshift
#if ENABLE_QPA
                                    , const uint32_t chromaShiftHor /*= 0*/, const uint32_t chromaShiftVer /*= 0*/
#endif
                                      )
{
  uint64_t uiTotalDiff;
  const  Pel*  pSrc0 = pic0.bufAt(0, 0);
  const  Pel*  pSrc1 = pic1.bufAt(0, 0);

  TCHECK(pic0.width  != pic1.width , "Unspecified error");
  TCHECK(pic0.height != pic1.height, "Unspecified error");

  if( rshift > 0 )
  {
#if ENABLE_QPA
    const   uint32_t  BD = rshift;      // image bit-depth
    if (BD >= 8)
    {
      const uint32_t   W = pic0.width;  // image width
      const uint32_t   H = pic0.height; // image height
      const double     R = double(W * H) / (1920.0 * 1080.0);
      const uint32_t   B = Clip3<uint32_t>(0, 128 >> chromaShiftVer, 4 * uint32_t(16.0 * sqrt(R) + 0.5)); // WPSNR block size in integer multiple of 4 (for SIMD, = 64 at full-HD)

      uint32_t x, y;

      if (B < 4) // image is too small to use WPSNR, resort to traditional PSNR
      {
        uiTotalDiff = 0;
        for (y = 0; y < H; y++)
        {
          for (x = 0; x < W; x++)
          {
            const           int64_t iDiff = (int64_t)pSrc0[x] - (int64_t)pSrc1[x];
            uiTotalDiff += uint64_t(iDiff * iDiff);
          }
          pSrc0 += pic0.stride;
          pSrc1 += pic1.stride;
        }
        return uiTotalDiff;
      }

      double wmse = 0.0, sumAct = 0.0; // compute activity normalized SNR value

      for (y = 0; y < H; y += B)
      {
        for (x = 0; x < W; x += B)
        {
          wmse += calcWeightedSquaredError(pic1,   pic0,
                                           sumAct, BD,
                                           W,      H,
                                           x,      y,
                                           B,      B);
        }
      }

      // integer weighted distortion
      sumAct = 16.0 * sqrt ((3840.0 * 2160.0) / double((W << chromaShiftHor) * (H << chromaShiftVer))) * double(1 << BD);

      return (wmse <= 0.0) ? 0 : uint64_t(wmse * pow(sumAct, BETA) + 0.5);
    }
#endif // ENABLE_QPA
    uiTotalDiff = 0;
    for (int y = 0; y < pic0.height; y++)
    {
      for (int x = 0; x < pic0.width; x++)
      {
        Intermediate_Int iTemp = pSrc0[x] - pSrc1[x];
        uiTotalDiff += uint64_t((iTemp * iTemp) >> rshift);
      }
      pSrc0 += pic0.stride;
      pSrc1 += pic1.stride;
    }
  }
  else
  {
    uiTotalDiff = 0;
    for (int y = 0; y < pic0.height; y++)
    {
      for (int x = 0; x < pic0.width; x++)
      {
        Intermediate_Int iTemp = pSrc0[x] - pSrc1[x];
        uiTotalDiff += uint64_t(iTemp * iTemp);
      }
      pSrc0 += pic0.stride;
      pSrc1 += pic1.stride;
    }
  }

  return uiTotalDiff;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

VTM中YUV-PSNR的计算 的相关文章

  • 【H.264/AVC视频编解码技术详解】十七:帧内预测编码的预测实现方法

    H 264 AVC视频编解码技术详解 视频教程已经在 CSDN学院 上线 视频中详述了H 264的背景 标准协议和实现 并通过一个实战工程的形式对H 264的标准进行解析和实现 欢迎观看 纸上得来终觉浅 绝知此事要躬行 只有自己按照标准文档
  • 哔哩哔哩 API

    常用查看技巧 UP主所有视频 https www bilibili com medialist play 这里写uid from space 最新投稿的视频 https www bilibili com newlist html API 参
  • VTM新手踩坑

    VTM踩坑实录 1 编码后yuv文件打开异常 2 编码帧数偏少 3 VTM命令行参数 1 编码后yuv文件打开异常 利用ffmpeg播放改文件 命令行 ffplay video size 宽x高 i file name yuv 时出现该画面
  • vlc-android配置实录

    听说vlc底层也用的ffmpeg 免费开源的 业界做的不错的 就来看看 从网上找了很多例子 也从github上找了好多demo 好多都不全 或者下载下来编译失败 官网上下载的vlc android就编译失败 下面列两个可以用的 一 有vlc
  • python PyAV库解析H264视频流及保存指定帧

    PyAV是一个视频处理库 可用于读取 写入和处理视频 要使用PyAV读取视频关键帧 首先需要安装PyAV 可以使用以下命令安装PyAV pip install av 安装完成后 您可以使用以下代码打开视频文件并读取关键帧 import av
  • HEVC学习之码流分析

    一 从分层编解码框架到NAL单元 以H 264为例 H 264适应不同网络之间的传输 主要原因是引入了分层结构 分为视频编码层 VCL 与网络抽象层 NAL 从而实现压缩编码与网络传输分离 通过H 264算法压缩的后的数据通过NAL VCL
  • pywt 安装学习

    安装 conda install c conda forge pywavelets github地址 里面有demo https github com PyWavelets pywt 这个是学习笔记 https blog csdn net
  • 使用Visual Studio编译ffmpeg

    一 首先参照下面的链接配置和编译 FFmpeg在VS2017下的编译 vs2017 ffmpeg源码编译 鱼儿 1226的博客 CSDN博客 vs2019编译ffmpeg源码为静态库动态库 完整步骤 亲测可行 ffmpeg vs 令狐掌门的
  • H.264 入门篇 - 11 (帧间预测 - DPB 管理策略)

    DPB 对解码图像的存储有个策略 更倾向于存储对后面编码有用的图像 也就是参考图像 虽然说 DPB 中也可以存储非参考图像 在DPB没满的时候 会无差别地把参考图像与非参考图像一并插入DPB中 但是一旦DPB满了之后 如果新重建的图像为参考
  • 几种前端h264播放器记录

    近期做了点工作记录一下 主要是将H264流在html5上进行播放 众所周知 大多数的 video组件都是支持FLV或者MP4以及m3u8格式的 而如果是WebRTC是直接集成好了 本次要求的环境主要是通过Websocket方式进行流传输 不
  • Nvidia Jetson 编解码开发(6)Jetpack 4.x版本Multimedia API 硬件编码开发--输入端对接Camera V4L2采集

    1 前言 Nvidia Jetson 编解码开发 2 Jetpack 4 x版本Multimedia API 硬件编码开发 集成encode模块 free xx的博客 CSDN博客 基于上篇继续开发 由于上篇只集成了encode模块 但是编
  • 详解JPEG编码格式

    参考文章1 参考文章2 MJPEG是一种视频压缩格式 其中的每一帧图像都使用JPEG编码 实际上 M J P E G
  • 【分享NVIDIA GTC 23大会干货】在 GPU 上使用 Video Codec SDK,CV-CUDA 和 TensorRT 加速现代云上视频应用 [SE51229]

    在 GPU 上使用 Video Codec SDK CV CUDA 和 TensorRT 加速现代云上视频应用 前言 基于现代 的视频流水线架构与运用场景 NVIDIA 视频处理的工具集 1 视频编解码工具 2 前后处理部分 CV CUDA
  • VLC搭建RTSP服务器的过程 -测试通过

    第一步 打开VLC 第二步 在媒体下拉菜单下 有一个子菜单 串流 如图所示 点击 串流 子菜单 弹出一个窗口 如下图所示 添加一个你要串流的本地文件 我刚才传给你的那个长一点的文件 第三步 会出现如下的界面 第五 点击下一步 第六步 在下拉
  • 【H.264/AVC视频编解码技术详解】十九、熵编码(5):CABAC语法元素的二值化

    H 264 AVC视频编解码技术详解 视频教程已经在 CSDN学院 上线 视频中详述了H 264的背景 标准协议和实现 并通过一个实战工程的形式对H 264的标准进行解析和实现 欢迎观看 纸上得来终觉浅 绝知此事要躬行 只有自己按照标准文档
  • 【数据压缩3】AVI文件格式分析及问题回答+WAV文件格式分析

    目录 AVI文件问题回答 1 AVI文件音频和视频的数据是如何放置的 交织放置还是连续放置 2 AVI文件一个视频帧大约占据多少字节 一个音频数据块大约占用多少字节 WAV文件格式分析 文件概述 文件格式 RIFF区块 FORMAT区块 D
  • ffpmeg相对无损转换mkv到mp4,保留标签、封面等元数据

    其实这个无损是相对无损 不是绝对无损 因为mkv封装支持的格式 标签等是比mp4封装要多的 比如mkv可以封装wav音频 mp4不能封装wav音频 所以这里的无损的前提是该mkv的媒体流 标签 TAG 封面图等 都是Mp4本身支持的 才能无
  • ffmpeg + x264+ x265 + libde265 + opengl es display

    这是手机直播推送流 https github com wangzuxing MyFFmpegH264H265YUVOpenGL https github com jacke121 MyFFmpegH264H265YUVOpenGL
  • H5播放之Rtsp转Websocket点播录像抓拍

    H5播放之Rtsp转Websocket点播录像抓拍 HLS的延时 websocket播放 实现思路 广大网友们 很久没上CSDN了 暨上次RTSP转HLS文章发布以来 一直还有一个问题没有解决 如何避免HLS切片带来的不可避免的高延时 HL
  • Android交叉编译OpenCV+FFmpeg+x264的艰难历程

    前言 如果你没有兴趣看完本文 只想获得可编译的代码或编译后的产物 可以直接点击下面的链接 跟随步骤编译代码或直接下载我编译好的产物 注 编译顺序要按照 x264 gt FFmpeg gt OpenCV 这样来 x264 FFmpeg Ope

随机推荐

  • oracle RAC ORA-03113 错误解决

    好久 没有更新博客 太懒了 这咋换工作呢 1 错误现象 数据库 客户端连接不正常 频繁报 ORA 03113 错误 oracle 文档中对这个错误这样解释 ORA 03113 错误就是说连接到数据库的网络中断了 有些错误由于频繁出现 原因复
  • res_company_white_url.py 详解

    res company white url py 主要作用是 在数据库中建立一个表 存放白名单的URL 当我们读取文件时 先判断Referer是否在白名单中 如果不在则自动转到一个图片文件 防止盗链 接下来我们看一下主要代码 class C
  • unexpected keyword argument 'renderer'-DjangoUeditor

    今天在集成DjangoUeditor按照官方的Github集成之后 本以为就可以看到后台了没想到直接报错 render got an unexpected keyword argument renderer 报错93行 boundfield
  • 【QT】——06_带参数的信号(笔记)

    信号重载 说明 信号是可以重载的 相同的名字不同的参数 在发射信号的时候给值 emit musicSignal 100 音乐菜单 主窗口 h 创建一个带参的槽来处理信号 注意槽的参数要与信号一致 void dealMusic2 int QS
  • 《Hadoop学习笔记系列》二.Hadoop分布式文件系统 HDFS

    0 Hadoop分布式文件系统 HDFS HDFS以流式数据访问模式来存储超大文件 运行与商用硬件集群上 1 流式数据访问 HDFS的构建思路 一次写入 多次读取是最高效的访问模式 2 Block数据块 HDFS基本读写单位 类似于磁盘的页
  • STM32的ADC采样与多通道ADC采样

    一 单通道采样 参考资料 STM32库开发实战指南 刘火良 杨森著 原理性质的东西还是少讲 因为上面那本书里面讲解的很详细了 直接来看硬件电路图 这里使用的是3362电位器 10K 即用STM32来测量PB0和GND两端的电压 这样的电路设
  • 一篇明白SQL的执行顺序

    这是一条标准的查询语句 这是我们实际上SQL执行顺序 我们先执行from join来确定表之间的连接关系 得到初步的数据 where对数据进行普通的初步的筛选 group by 分组 各组分别执行having中的普通筛选或者聚合函数筛选 然
  • 小谈HashMap与ConcurrentHashMap

    HashMap JDK7 在JDK7中 HashMap通过数组加链表的形式存储 当元素个数达到阈值 并且数组下标已经存在元素 则会进行扩容 如果数组下标不存在元素 则直接添加 不会扩容 JDK7中添加元素使用的是头插法 在高并发的环境下可能
  • [算法通关村] 1.3 链表的删除

    上一节我们谈到了链表的头插 尾插 中间插入的方法 忘记的小伙伴可以复习一下 算法通关村 1 2 链表的插入 接下来 完成链表的删除工作 我们在上一节的学习中 分别在链表的开头 中间和结尾插入了节点 现在我们想使链表恢复原来的样子 即 1 g
  • 更多的服务商从业者都开始关注刷脸支付

    刷脸支付就是通过人脸进行支付 简单来说消费者在接入蜻蜓的商家结账付款时 只需将脸面对蜻蜓上的摄像头即可完成支付 在这一过程中用户甚至不需要用手机 支付效率相比扫码支付更加的高效 此外由于支付宝刷脸支付是基于3D人脸识别技术 在安全也要比扫码
  • 【机器学习】编码、创造和筛选特征

    在机器学习和数据科学领域中 特征工程是提取 转换和选择原始数据以创建更具信息价值的特征的过程 假设拿到一份数据集之后 如何逐步完成特征工程呢 文章目录 一 特性类型分析 1 1 数值型特征 1 2 类别型特征 1 3 时间型特征 1 4 文
  • SpringMVC的全注解开发

    文章目录 一 spring mvc xml 中组件转化为注解形式 二 DispatcherServlet加载核心配置类 三 消除web xml 一 spring mvc xml 中组件转化为注解形式 跟之前全注解开发思路一致 xml配置文件
  • 2.c语言中将两个整数相加

    上一个文章 我讲述了如何输出文字 接下来我就来讲讲有一丢丢难度的算法了 这个算法就是学习如何将两个整数相加 这是学习如何编写一个计算机软件的第一步 现在我就为你们来一一讲解 代码如下 include
  • StringBuffer integer

    StringBuffer 一 1 StringBuffer是一个容器 而容器的特点是可以修改 基本操作是增添删改 这也是它与StringBuffer的主要区别 2 线程安全 可变的字符序列 是一个字符缓冲区 也是final型 不能被继承 3
  • java基础-垃圾收集器及其回收算法的介绍

    文章目录 前言 一 垃圾收集器管理的区域 二 垃圾收集器的回收步骤 1 阶段一 判断对象是否存活 2 阶段二 筛选 三 垃圾收集算法 1 分代收集理论 理论基础 2 标记 清除算法 3 标记 复制算法 4 标记 整理算法 四 补充 前言 最
  • v8所有例子在里面

    https github com nodejs nan blob master doc methods md
  • 线程间怎么交换数据_在LLVM后端实现跨通道数据搬移

    作者 汪岩 AMD GPU的每个CU有一个64kB的存储空间 称为本地数据共享 Local Data Share LDS 用于同一计算单元中的work group内各个work item之间的低延迟通信和数据共享 LDS配置为32个bank
  • 为了通过面试,要刷多少道leetcode题?一文解答你的疑惑。

    想要学习算法 应付笔试或者应付面试手撕算法题 相信大部分人都会去刷 Leetcode 有读者问 如果我在 leetcode 坚持刷它个 500 道题 以后笔试 面试稳吗 这里我说下我的个人看法 我认为不稳 下面说说为啥不稳以及算法题应该如何
  • Acwing 908. 最大不相交区间数量

    include
  • VTM中YUV-PSNR的计算

    名词解释 参见文章cnblogs 什么是SAD SAE SATD SSD SSE MAD MAE MSD MSE PSNR的计算 较为标准的MSE计算公式和PSNR计算公式如下 引用链接 CSDN 图像的峰值信噪比 PSNR 的计算方法 这