qqp123123 2024-11-06 22:46 采纳率: 0%
浏览 13

AV1内tune=ssim的情况下的rdo模型是什么样的

有人知道aom编码器内部在--tune=ssim的情况下是如何进行调整拉个朗日乘子的吗?
源代码内会调用 av1_set_mb_ssim_rdmult_scaling函数设置对rdmult的缩放因子,但是为什么这样设置有人知道吗,它的rdo模型是怎么样的?特别是里面那个指数函数拟合代表什么意思?

void av1_set_mb_ssim_rdmult_scaling(AV1_COMP *cpi) {
  const CommonModeInfoParams *const mi_params = &cpi->common.mi_params;
  const MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
  uint8_t *y_buffer = cpi->source->y_buffer;
  const int y_stride = cpi->source->y_stride;
  const int block_size = BLOCK_16X16;

  const int num_mi_w = mi_size_wide[block_size];
  const int num_mi_h = mi_size_high[block_size];
  const int num_cols = (mi_params->mi_cols + num_mi_w - 1) / num_mi_w;
  const int num_rows = (mi_params->mi_rows + num_mi_h - 1) / num_mi_h;
  double log_sum = 0.0;

  // Loop through each 16x16 block.
  for (int row = 0; row < num_rows; ++row) {
    for (int col = 0; col < num_cols; ++col) {
      double var = 0.0, num_of_var = 0.0;
      const int index = row * num_cols + col;

      // Loop through each 8x8 block.
      for (int mi_row = row * num_mi_h;
           mi_row < mi_params->mi_rows && mi_row < (row + 1) * num_mi_h;
           mi_row += 2) {
        for (int mi_col = col * num_mi_w;
             mi_col < mi_params->mi_cols && mi_col < (col + 1) * num_mi_w;
             mi_col += 2) {
          struct buf_2d buf;
          const int row_offset_y = mi_row << 2;
          const int col_offset_y = mi_col << 2;

          buf.buf = y_buffer + row_offset_y * y_stride + col_offset_y;
          buf.stride = y_stride;

          var += av1_get_perpixel_variance_facade(cpi, xd, &buf, BLOCK_8X8,
                                                  AOM_PLANE_Y);
          num_of_var += 1.0;
        }
      }
      var = var / num_of_var;

      // Curve fitting with an exponential model on all 16x16 blocks from the
      // midres dataset.
      var = 67.035434 * (1 - exp(-0.0021489 * var)) + 17.492222;

      // As per the above computation, var will be in the range of
      // [17.492222, 84.527656], assuming the data type is of infinite
      // precision. The following assert conservatively checks if var is in the
      // range of [17.0, 85.0] to avoid any issues due to the precision of the
      // relevant data type.
      assert(var > 17.0 && var < 85.0);
      cpi->ssim_rdmult_scaling_factors[index] = var;
      log_sum += log(var);
    }
  }

  // As log_sum holds the geometric mean, it will be in the range
  // [17.492222, 84.527656]. Hence, in the below loop, the value of
  // cpi->ssim_rdmult_scaling_factors[index] would be in the range
  // [0.2069, 4.8323].
  log_sum = exp(log_sum / (double)(num_rows * num_cols));

  for (int row = 0; row < num_rows; ++row) {
    for (int col = 0; col < num_cols; ++col) {
      const int index = row * num_cols + col;
      cpi->ssim_rdmult_scaling_factors[index] /= log_sum;
    }
  }
}

  • 写回答

1条回答 默认 最新

  • 香格里辣 2024-11-06 22:47
    关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    这段代码是用于设置AV1编码器的拉格朗日乘子缩放因子的函数,特定的场景是当编码器使用--tune=ssim选项时。SSIM(结构相似性度量)是一种用于评估图像质量的指标,该函数的目标是根据SSIM标准调整编码器的决策过程以优化图像质量。具体来说,该函数计算每个宏块(Macroblock)的方差,并使用这个方差值来调整拉格朗日乘子缩放因子。下面简要描述该函数的操作和背后的RDO(Rate-Distortion Optimization)模型:

    1. 函数首先计算每个宏块的方差(用于表示图像局部区域的纹理复杂程度)。这里对每个宏块内部的多个小宏块进行遍历,并计算其像素方差。这是基于观察到的图像纹理复杂度和SSIM之间的关系。方差越大,意味着图像纹理越复杂。
    2. 然后,函数使用一种指数模型来调整计算出的方差值。这可能是为了校正原始的方差值或将其转换到某个特定范围。这步操作的目的是将方差映射到一个合适的范围,以便于后续的使用。具体来说,此步骤的目的是调整优化问题的目标函数权重,这些权重会影响编码器的决策过程。
    3. 函数接着计算所有宏块的几何平均方差(通过计算所有宏块方差的自然对数的平均值然后取指数得到)。这个几何平均方差代表了整个帧的“平均纹理复杂性”。这一步的目的是为了对之前计算出的缩放因子进行进一步的归一化。
    4. 最后,函数将每个宏块的缩放因子除以几何平均方差值。这样做是为了确保所有宏块的缩放因子相对于整个帧的复杂度都有一个相对合理的比例。这一步的目的是确保编码器的决策过程不仅考虑单个宏块的特性,还考虑整个帧的上下文信息。

    总的来说,这个函数通过计算每个宏块的方差并根据这些方差值来调整拉格朗日乘子缩放因子,从而优化AV1编码器的决策过程以改善图像的SSIM质量。背后的RDO模型是通过对整个帧的复杂度进行建模并利用这些复杂度信息来调整优化问题的目标函数权重来实现的。这样可以使编码器在权衡码率和失真时更加精准,以达到更好的编码效果。

    评论

报告相同问题?

问题事件

  • 修改了问题 11月6日
  • 创建了问题 11月6日