我正在尝试复制 Adobe After Effects 中称为“光学补偿”的效果。我认为这与镜头畸变类似。但那里使用的公式不适合。 该效果有几个选项可以操作。该效果有几个参数可以更改。
在此视频中我将 FOV 值从 0 度动画到 180 度;中心 = 540,960
还有图像示例:
看起来像桶形畸变或鱼眼畸变。
我尝试了不同的公式。例如“镜头校正模型”
但是我不明白如何仅使用 FOV 和中心值来计算所有这些参数。
有谁知道如何达到这个效果吗?应该使用什么公式? 到处都描述了如何修复“镜头畸变”。但如何在图片上应用这样的效果呢?
经过一番研究,我发现了 Mathworks 实现用于桶变换。
代码
[xi,yi] = meshgrid(1:ncols,1:nrows);
xt = xi - ncols/2;
yt = yi - nrows/2;
[theta,r] = cart2pol(xt,yt);
a = 1; % Try varying the amplitude of the cubic term.
rmax = max(r(:));
s1 = r + r.^3*(a/rmax.^2);
[ut,vt] = pol2cart(theta,s1);
ui = ut + ncols/2;
vi = vt + nrows/2;
ifcn = @(c) [ui(:) vi(:)];
tform = geometricTransform2d(ifcn);
I_barrel = imwarp(I,tform,FillValues=fill);
imshow(I_barrel)
我在苹果金属中的实现
fragment float4 opticsCompensationFragment(metalpetal::VertexOut vertexIn [[ stage_in ]],
texture2d<float, access::sample> inputTexture [[ texture(0) ]],
sampler inputTextureSampler [[ sampler(0) ]]) {
float2 center = float2(0.5, 0.5);
// Shift the origin to the center of the image
float2 st = vertexIn.textureCoordinate - center;
// Convert the Cartesian x- and y-coordinates to cylindrical angle (theta) and radius (r) coordinates
float theta = sqrt(st.x * st.x + st.y * st.y);
float r = atan2(st.y, st.x);
// Try varying the amplitude of the cubic term.
float a = 0.1;
// add a cubic term to r so that r changes nonlinearly with distance from the center pixel.
float s1 = r + (r*r*r)*(a/(r*r));
// Convert back to the Cartesian coordinate system. Shift the origin back
float ut = theta * cos(s1) + center.x;
float vt = theta * sin(s1) + center.y;
return inputTexture.sample(inputTextureSampler, float2(ut, vt));
}
但是我的结果不是这样的。
唯一的区别是,在 Mathworks 的代码中,他们使用 meshwarp,但我尝试仅使用 片段着色器 来实现这一点。 我的代码可能有什么问题?
一个问题是您在笛卡尔坐标的转换中混淆了半径和角度的公式(或者至少您为这些变量选择了混淆的名称)。因此,当您修改
r
变量时,您实际上是在更改角度,而您想要更改的半径位于未更改的 theta
变量中。