void VideoFrameTransform::generateKernelAndFilteringConfig()

in Transform360/Library/VideoFrameTransform.cpp [227:319]


void VideoFrameTransform::generateKernelAndFilteringConfig(
  int top,
  int bottom,
  float angle,
  float sigmaY,
  const Mat& kernelY,
  int inputWidth,
  int inputHeight,
  int transformMatPlaneIndex) {
  float sigmaX = min(
    0.5 * inputWidth, sigmaY / (
      cos(angle) + kEpsilon));

  // Build a basic 1D kernel along X direction
  Mat kernelX = calculateKernel(sigmaX);

  int numHorizontalSegments = ctx_.adjust_kernel ?
    ctx_.num_horizontal_segments : 1;
  vector<SegmentFilteringConfig> configs;
  int segmentWidth = ceil(1.0 * inputWidth / numHorizontalSegments);

  // Will be used to normalize the kernel scaling factor
  double baseEffectiveRatio = getEffectiveRatio(0.0, 0.0);

  // Calculate the kernel and filtering config for each of the horizontal
  // tile/segment. These tiles are all in the same vertical segment which is
  // created in generateKernelsAndFilteringConfigs.
  for (int i = 0; i <  numHorizontalSegments &&
      i * segmentWidth < inputWidth; ++i) {
    segmentFilteringConfigs_[transformMatPlaneIndex].emplace_back(
      SegmentFilteringConfig(
        i * segmentWidth,
        top,
        min(segmentWidth, inputWidth - i * segmentWidth),
        bottom - top + 1));

    if (ctx_.adjust_kernel) {
      // Calculate the average yaw and pitch values of a tile, from which
      // we calcuate the "distance" (in radians) between the point
      // (average yaw, average pitch) and the input point
      // (fixed_yaw, fixex_pitch).
      // Here, the origins of the yaw and pitch are at the center of the frame.
      // inputWidth corresponds to 2 * M_PI in radians for yaw, and inputHeight
      // corresponds to M_PI in radians for pitch. Yaw is changed from 0 to
      // PI when moving from center to left, and from 0 to -PI when moving from
      // center to right. Pitch is changed from 0 to 0.5 * PI when moving from
      // center to top, and from 0 to -0.5 * PI when moving from center to
      // bottom.
      float avgYaw = 2 * M_PI * (
        (i * segmentWidth +
         0.5 * min(segmentWidth, inputWidth - i * segmentWidth))
        - 0.5 * inputWidth) / inputWidth;
      float avgPitch = 0.5 * M_PI * (inputHeight - top - bottom) / inputHeight;

      float yaw = ctx_.fixed_yaw * M_PI / 180.0f;
      float pitch = ctx_.fixed_pitch * M_PI / 180.0f;
      float offset = std::abs(ctx_.fixed_cube_offcenter_z);

      // Check if yaw and pitch are both 0 and we should use reverse direction
      // of the offset instead.
      if (std::abs(yaw) < kEpsilon && std::abs(pitch) < kEpsilon && (
          std::abs(ctx_.fixed_cube_offcenter_x) > kEpsilon ||
          std::abs(ctx_.fixed_cube_offcenter_y) > kEpsilon ||
          ctx_.fixed_cube_offcenter_z > kEpsilon)) {  // check Z > 0 explicitly
        offset = sqrtf(
            ctx_.fixed_cube_offcenter_x * ctx_.fixed_cube_offcenter_x +
            ctx_.fixed_cube_offcenter_y * ctx_.fixed_cube_offcenter_y +
            ctx_.fixed_cube_offcenter_z * ctx_.fixed_cube_offcenter_z);
        yaw = atan2f(
            -ctx_.fixed_cube_offcenter_x / offset,
            -ctx_.fixed_cube_offcenter_z / offset);
        pitch = asinf(-ctx_.fixed_cube_offcenter_y / offset);
      }

      double dist = angularDistance(
        yaw,
        pitch,
        avgYaw,
        avgPitch);

      double effectiveRatio = getEffectiveRatio(dist, offset);
      double kernelScalingFactor =
        ctx_.kernel_adjust_factor * baseEffectiveRatio / effectiveRatio;
      Mat adjustedKernelX = calculateKernel(kernelScalingFactor * sigmaX);
      Mat adjustedKernelY = calculateKernel(kernelScalingFactor * sigmaY);
      filterKernelsX_[transformMatPlaneIndex].emplace_back(adjustedKernelX);
      filterKernelsY_[transformMatPlaneIndex].emplace_back(adjustedKernelY);
    } else {
      filterKernelsX_[transformMatPlaneIndex].emplace_back(kernelX);
      filterKernelsY_[transformMatPlaneIndex].emplace_back(kernelY);
    }
  }
}