【发布时间】:2014-11-10 08:40:13
【问题描述】:
所以我有一台带广角镜头的相机。我知道畸变系数、焦距、光学中心。我想不扭曲从这台相机获得的图像。我第一次尝试使用 OpenCV (cv::undistort),效果很好,但是太慢了。
现在我想在 gpu 上执行此操作。在 http://willsteptoe.com/post/67401705548/ar-rift-aligning-tracking-and-video-spaces-part-5 中记录了一个着色器正在执行此操作
公式可以在这里看到: http://en.wikipedia.org/wiki/Distortion_%28optics%29#Software_correction
所以我去实现了我自己的版本作为 glsl 着色器。我在 0..1 之间的角上发送一个纹理坐标的四边形。 我假设到达的纹理坐标是未失真图像的坐标。我计算对应于我的纹理坐标的扭曲点的坐标。然后我对扭曲的图像纹理进行采样。
使用此着色器没有在最终图像中发生任何变化。我通过 cpu 实现发现的问题是,系数项非常接近于零。通过半径平方等,数字变得越来越小。所以我有一个缩放问题 - 我不知道该怎么做!我尝试了所有方法...我想这很明显,因为这种过程似乎适用于很多人。
为简单起见,我省略了切向失真校正。
#version 330 core
in vec2 UV;
out vec4 color;
uniform sampler2D textureSampler;
void main()
{
vec2 focalLength = vec2(438.568f, 437.699f);
vec2 opticalCenter = vec2(667.724f, 500.059f);
vec4 distortionCoefficients = vec4(-0.035109f, -0.002393f, 0.000335f, -0.000449f);
const vec2 imageSize = vec2(1280.f, 960.f);
vec2 opticalCenterUV = opticalCenter / imageSize;
vec2 shiftedUVCoordinates = (UV - opticalCenterUV);
vec2 lensCoordinates = shiftedUVCoordinates / focalLength;
float radiusSquared = sqrt(dot(lensCoordinates, lensCoordinates));
float radiusQuadrupled = radiusSquared * radiusSquared;
float coefficientTerm = distortionCoefficients.x * radiusSquared + distortionCoefficients.y * radiusQuadrupled;
vec2 distortedUV = ((lensCoordinates + lensCoordinates * (coefficientTerm))) * focalLength;
vec2 resultUV = (distortedUV + opticalCenterUV);
color = texture2D(textureSampler, resultUV);
}
【问题讨论】:
-
以下是 WebGL 中的一些类似工作:github.com/jywarren/fisheyegl 但我们看到非方形图像出现错误,如果有人能做到,我们真的可以使用一些帮助:stackoverflow.com/questions/45110817/…
-
你真的需要在着色器中计算 UV 贴图吗?由于失真是恒定的,因此您只需执行一次。在开始渲染之前,可以使用 OpenCV 在 CPU 上简单地计算 UV 贴图。
标签: opengl glsl shader gpu distortion