openvr_survivor第二期开发活动:VR畸变

开发简介

  • 开发主题:VR畸变
  • 参与人员:helen,xin,云淡风清,ice等(VR开发者QQ群:538874606)
  • 项目代码
  • gitter讨论链接
  • 主要内容
    • VR畸变/反畸变介绍
    • openVR显示接口介绍
    • zemax软件设计光学系统
    • 反畸变处理

这里主要是分享一下我们对于这方面问题的一些看法,文档可能存在一些错误和不足,希望能够得到大家的批评和建议,与大家一起将这部分内容做的更加完善,持续更新.

VR畸变/反畸变介绍

在VR显示系统中,显示的模型为:人眼—透镜—显示屏.人眼通过透镜得到大的FOV,从而带来很强的沉静感,但透镜带来大FOV的同时,也会产生一些副作用,例如几何畸变和色散.

  • 几何畸变
    这里简要描述一下畸变和反畸变的过程:显示屏上图像如下图(图片使用distortionizer生成)
    openvr_survivor第二期开发活动:VR畸变_第1张图片
    (distortion_normal)
    上图中的横/纵线组成的方格图,横/纵各自都是笔直的直线,并且横/纵线互相垂直.这是在人眼直接观看屏幕时的情况,在VR显示系统中,人眼和显示屏之间增加了一个透镜,因为透镜的光学原因,最终看到的图像会是下图这样的
    openvr_survivor第二期开发活动:VR畸变_第2张图片
    (distortion_pincushion)
    该图中的横/纵直线不再互相垂直,并且可以看到明显的内凹(“枕型”),并且随着离圆圈中心的距离越远内凹幅度越大.这就是镜片产生的”枕型”畸变.人眼通过透镜观显示屏,显示屏上显示的是”distortion_normal”图片,而人眼最终看到的是”distortion_pincushion”图片,这就是人眼看到的畸变图像.
    为了使人眼看到的图像为”distortion_normal”图片,我们可以通过修改显示屏上的显示内容,对原始图像进行预畸变处理,从而抵消镜片产生的畸变影响(还有一种方式是通过多个透镜单元,消除透镜产生的畸变,实现无畸变镜片,这种方式目前普及率低,这里不详细描述这种情况).
    openvr_survivor第二期开发活动:VR畸变_第3张图片
    (distortion_barrel)
    上图中的横/纵直线不互相垂直,并且可以看到明显的外凸(“桶型”),并且随着离圆圈中心的距离越远外凸幅度越大,显示屏上的图像进行了预畸变处理后,这与”distortion_pincushion”正好相反(外凸和内凹的幅度必须相同,才能将图片完美还原为最初的图像).显示屏显示”distortion_barrel”图片,人眼通过透镜观看到的图像就会是正常的图像,即”distortion_normal”图片那样.
    这里是我在ShaderToy上做的一个畸变和反畸变的动画.
    原图:
    openvr_survivor第二期开发活动:VR畸变_第4张图片
    k<0时,”枕”型畸变:
    openvr_survivor第二期开发活动:VR畸变_第5张图片
    k>0时,”桶”型畸变:
    openvr_survivor第二期开发活动:VR畸变_第6张图片
    之前翻译过一些关于畸变的一些链接:
    Understanding the Oculus Rift Distortion Shader
    处理VR透镜畸变的三种方法
    Distortion Correction
    VR光学设计的关键参数
  • 色散
    白光通过透镜,不同颜色的光因波长的不同而出现颜色分离的现象,你可以拆下一个cardboard或其他VR透镜,然后通过眼睛观察,边缘的地方会出现如下图所示色散现象:
    openvr_survivor第二期开发活动:VR畸变_第7张图片

openvr显示相关接口

openvr显示相关接口

使用Zemax设计VR透镜

感谢Steven Cui分享了这部分内容,原稿在这里下载,下面是这份文稿的内容

基本原理

VR透镜的目的是为了将LCD显示屏成一个放大的虚像。
放大的目的有两个:1是显示屏靠人眼太近,人根本看不清,祖先没有进化出这种功能;2是FOV(field of view)太小。
所以,我们开始设计个单透镜,回顾下初中光学知识,我们需要将LCD屏放在一倍焦距之内,这就是基本原理。
openvr_survivor第二期开发活动:VR畸变_第8张图片
下面开始说zemax的设计过程
ZEMAX的软件设计界面如下
openvr_survivor第二期开发活动:VR畸变_第9张图片
openvr_survivor第二期开发活动:VR畸变_第10张图片
openvr_survivor第二期开发活动:VR畸变_第11张图片
上图中,左边是LCD显示屏,中间是透镜,最右侧是EYE人眼位置。这里偷了个懒,利用一个小技巧,从人眼向负方向走25.4cm就是我们想设计的像距。

设计初始透镜结构

确定了基本原理后,我们在镜头数据编辑窗口建立一个初始的透镜结构,这个结构是根据某家VR眼镜参数来设计的。
openvr_survivor第二期开发活动:VR畸变_第12张图片
上面的图,就给出了显示屏和透镜、人眼的位置等关系。ZEMAX里面的三者的位置,及透镜的厚度,就是按照这份资料来的。注意,此处zemax是设计的单眼。另外,ZEMAX中透镜是有多个平面组成的,比如刚才这个透镜是由四个平面组成,ZEMAX里面所有的透镜
都是由多个面组成。虽然是4个面组成一个透镜,但是材料我都是用的PMMA,因此它们4个就组成了一个整体透镜。这样,建立透镜的初始结构,这步就完成了。

优化

设置变量,进行优化。透镜中我们不知道两个曲面的曲率,那么就设置为变量,并且我将第一个平面设为非球面,为了更好的成像质量。开始优化,就OK了,接下来我们对结果进行分析。

分析

我们来对设计结果进行几方面的分析:
第1)方面:看色散
openvr_survivor第二期开发活动:VR畸变_第13张图片
注意,这里面的红绿蓝是表示波长。这只是色散,没有畸变问题。
这款VR镜头设计得其实非常差,因为分辨率很差,弥散斑很重,大家就先看个思路哈
第2)方面:看畸变
openvr_survivor第二期开发活动:VR畸变_第14张图片
openvr_survivor第二期开发活动:VR畸变_第15张图片
这是畸变网格的量化形式,这就是咱们需要的。第一列和第二列的是网格节点,刚才发的是12*12的网格,对应的第一列范围为[-6,6]。刚才(6,6)这个点的畸变只有8%,是因为这是中心的畸变。
openvr_survivor第二期开发活动:VR畸变_第16张图片
openvr_survivor第二期开发活动:VR畸变_第17张图片
刚才我们讨论的都是视场1的,也就是色散图中的第一个中心位置区域的畸变情况。
下面先把三个视场的图都画出来
openvr_survivor第二期开发活动:VR畸变_第18张图片
openvr_survivor第二期开发活动:VR畸变_第19张图片
我没有细研究过这三者如何统一起来
下面是边缘位置,也就是3位置的数据复制过来
openvr_survivor第二期开发活动:VR畸变_第20张图片
看这个数据,就会发现畸变非常大。这个例子可以很生动的说明畸变情况。

反畸变处理

OSVR反畸变处理

OSVR提供的反畸变工具:distortionizer,这个工具能够处理畸变,并且提供了开源代码,原理介绍,以及使用步骤:
OSVR:distortionizer开源项目
OSVR畸变校正
OSVR视图变换
OSVR反畸变工具使用教程

matlab上做反畸变处理

据了解有一些厂家在设计DSP的IC,来实现反畸变的功能,从而减少GPU的负担,流程如下:
算法理论设计—>matlab仿真—>FPGA验证—>固化ASIC.
其中接触到的一个matlab仿真代码,这部分代码不方便公开,文档介绍见这里,列出原理,大概如下:
1. 参数读取/初始化
2. 加载图片,读取图片宽,高,像素值(R,G,B),原图尺寸512x1024.
3. 利用反畸变模型 f(r)=1+k1r2+k2r4+k3r6 f ( r ) = 1 + k 1 ∗ r 2 + k 2 ∗ r 4 + k 3 ∗ r 6 生成,32x32的畸变mesh表distort_table
坐标归一化处理,并把坐标原点从原始坐标(0,0)移到原始坐标的中心(256,256)位置.此时坐标系的矩形图上,左上是(-1,1),右上(1,1),左下(-1,-1),右下(1.-1).
4. 对所有像素点进行反畸变处理(一次处理两个像素点),对归一化后的坐标点进行二次线性插值(之前整理了一下插值的概念,见这里),从畸变列表中获得到该点的畸变参数distort_factor_x,然后获得预畸变值predis_factor.接着重新映射回原坐标result_r_x_dly1值,根据坐标值和原图片像素值,执行二次线性插值获得目标像素值.
5. 将所有新像素组成图像
原始图片
openvr_survivor第二期开发活动:VR畸变_第21张图片
根据镜片的k1,k2,k3参数,带入反畸变模型,经过matlab处理后的畸变图
openvr_survivor第二期开发活动:VR畸变_第22张图片

openVR反畸变处理

基于openVR,我们也制作了一个反畸变的算法,利用的反畸变模型为: f(r)=1+k1r2+k2r4+k3r6 f ( r ) = 1 + k 1 ∗ r 2 + k 2 ∗ r 4 + k 3 ∗ r 6 与上一个方法的畸变模型相同.代码见openvr_survivor

最后

感谢ice,xin,云淡风清等开发者,我们一起用空闲时间完成开发活动,这是一个开始,我们希望更多的人可以加入到我们当中来,VR还处于很初期的阶段,我们通过努力,也许可以给VR的发展带来一些好的东西,分享的过程也是一个很好的互相学习的过程,openvr_survivor下一期活动再会:-).

参考资料:

  1. a flexible new technique for camera calibration
  2. distortionizer
  3. correcting_lens_distortions
  4. lens distortion
  5. A computational model for the stereoscopic optics of a head-mounted display
  6. Using Texture Maps to Correct for Optical Distortion in Head-Mounted Displays
  7. rational radial distortion models with analytical undistortion formulae
  8. A Family of Simplified Geometric Distortion Models for Camera Calibration
  9. distortion(optics)

你可能感兴趣的:(我的开源项目)