VR镜头抗畸变基本算法探讨

举报
平平哥 发表于 2020/02/27 10:38:14 2020/02/27
【摘要】 在Cardboard VR的体验形式下,探讨采取哪些算法,可以比较好的处理透镜产生的图形畸变。

VR终端的体验有多种形式,除了现在比较成熟的VR一体机、VR眼镜以外,还有基本的Cardboard体验。

在Cardboard的体验形式下,如需要取得比较好的体验效果,如何比较好的处理透镜产生的图形畸变关系到最终的用户体验。


什么是畸变

在几何光学中,畸变是与直线投影的偏差,它是光学像差(即光经过透镜后产生的图像失真或模糊)的一种形式。而在VR眼镜中,我们所涉及的畸变都是径向畸变,即产生的图像变形都是径向对称的,这也是由摄像镜头的径向对称性所决定的。径向畸变通常有三种形式:
1、 桶形畸变
即图像放大率随着距光轴的距离而减小。在这样的畸变中,直线在中心向外凸出,像桶一样。

1582769836504949.png

2、 枕形畸变
图像放大率随着距光轴的距离而增加。在这样的畸变中,直线穿过图像向内弯曲,正方形的四个角外发拉长,像枕头一样。

1582769855268661.png

3、 胡子畸变
胡子畸变是上面两种类型的混合物,在这样的畸变中,它开始于靠近图像中心的桶形失真,并逐渐变成朝向图像周边的枕形失真,使得框架上半部分的水平线看起来像车把胡须。

1582769871797467.png

在数学上,除了胡子畸变以外,桶形和枕形畸变是二次的,这意味着它们随着距中心的距离的平方而增加。在VR中,我们只需要关注桶形和枕形畸变。


VR眼镜中的畸变是如何产生的

在VR眼镜中,为了获取得沉浸式的体验,需要给用户提供比较大的视场角(FOV),作为廉价的VR方案,肯定不可能在用户面前放上一个超大的曲面显示屏。替代方案就是在用户眼前小的显示屏上放置一个放大透镜。
效果如下图所示:

1582769967653556.jpg

这样有个靠近眼睛的透镜,可以让用户获得比较大的视场角,但这样做的代价就是光线经过透镜后会产生径向畸变,视角场越大,畸变就会越严重。
如下图所示,正常的图像经过放大透镜后会产生枕形畸变。

1582770022410459.jpg

在正常情况下,透镜的曲率越大,产生的畸变就会越严重。


VR眼镜中的畸变纠正办法

那么如何让人眼通过VR眼镜的透镜看到正常的图像,其解决办法就是提前对显示屏上输出的图片进行畸变纠正,即反向畸变。
将输出到显示屏上的图像转换成对应的桶状畸变,这样经过透镜到达人眼之后,就会反向形成正常的图像了。

1582770176366659.jpg

相关的畸变公式

相关的畸变公式有两个,其一是zhang(1999) 证明了具有两个系数的多项式径向畸变模型,模拟为如下公式:

1582770475958066.png

但在实际使用的过程中,如果要进行互相换算,需要解4次方程,代价有些高,所以一般情况下,我们都会使用另一个简单一点的,即费兹本(2001)近似径向畸变模型。公式如下:

1582770566304212.png

其中 ru 和 rd 分别是非畸变和畸变后的图像中心距离。α 是每一个镜片固有的常量系数。


具体算法的实现

由于费兹本公式中的r是围绕光轴所在图像中心点进行的计算,要使用这个公式,我们首先需要先进行坐标归一化,将图像中的坐标系向这个公式中的坐标系进行映射。
如下图所示,需要将左图的坐标映射为右图的座标。

1582770643634371.png

(xn,yn) 代表归一化后的坐标系,w 和 h 代表宽和高。
在使用公式完成反向畸变计算后,再进行坐标反向映射。

1582770680819919.png

搞清楚了上面这些东西,在Unity Shader中,使用一个简单的片元着色器就可以方便的搞定了,参考代码如下:
// 镜片的畸变常量系数
float alpha = 0.1f;
// 将坐标向费兹本公式坐标转换
float x = (2.0 * i.uv.x - 1.0) / 1.0f;
float y = (2.0 * i.uv.y - 1.0) / 1.0f;
// 将UV坐标转换为反向畸变后的坐标
float r = x * x + y * y;
float x3 = x / (1.0 - alpha * r);
float y3 = y / (1.0 - alpha * r);
float x2 = x / (1.0 - alpha * (x3 * x3 + y3 * y3));
float y2 = y / (1.0 - alpha * (x3 * x3 + y3 * y3));
// 将坐标进行反向转换
float i2 = (x2 + 1.0) * 1.0 / 2.0;
float j2 = (y2 + 1.0) * 1.0 / 2.0;


在上面的算法中可以暴露出镜片的畸变系统alpha。


再结合双目渲染的其他物理参数:比如瞳距、屏幕宽高、屏幕与镜片深度等,再进行相关的调整适配,就可以搞定大多数的双目渲染场景了。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

举报
请填写举报理由
0/200