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);
}
}
}