参考资料
https://www.bilibili.com/video/BV1Ae41127Yf?p=2
在日常生活中,光线与物体界面的交互,构成了我们眼里的图像。
但是为什么只有眼睛有成像,而像墙壁/桌子等这些平面上不会成像呢?
比如我举着一张纸在半空中,周围环境的物体上的光线也会照到这张纸上,但为什么纸还是一片空白没有图像呢?
原因是因为光线过于繁杂,纸上的一个点会接收到无数物体反射来的光线,从而什么都显示不出:
于是,针孔摄像机就出现了,当中间的孔足够小,纸上一个点就对应一条光线:
而我们的3D场景摄像机也是运用了类似的原理,假设现在有只可爱的小牛牛和一个摄像机,那么成像过程如下所示:
由上图可以看到,Image Plane有着自己的Image坐标系。
这样镜像翻转看终究有点别扭,我们不妨调整一下:
如果只看前面部分的投影牛牛:
这时投影的2维牛牛上每一个点都能对应着3D牛牛的唯一一个点。
为了方便后续公式推导,我们把牛牛去掉,只看正面的坐标系:
已知3D牛牛在3D世界某个点距离摄像机的深度Z和高度Y,以及摄像机的焦距f(focal length),那我们利用相似三角形公式,能很快推出2D牛牛的对应点具体坐标(x,y)
。
注:深度并不是点到摄像机center那根斜线,而是底部的Z长度
至此,我们就得到了3D牛牛世界坐标与图像平面坐标的换算关系:
且我们还能用这个换算关系推断出有意思的东西。
2D场景能保留3D场景的直线
和相交
信息,比如3D场景有根直线,那你在2D图像看也是直线。3D场景有两根线重合,那你在2D图像看那两根线也会重合。
但是2D场景难以保留2D场景的角度
和长度
信息。比如3D场景中有个铁路,并不相交,你却会觉得两根铁轨在无穷远处相交于一点:
我们可以用公式来进行类似的证明,假设现在3D场景有一根无限长的直线,那么在2D图像的投影是这样的:
我们可以看到距离无限远时,左边2D平面接收到的最下面的光线线很难再往下移动了,它们汇聚在一个叫Vanishing point的点上。
可以看到最后点聚集在(fa/c,fb/c)
坐标上。
且在现实中,我们很难判断2D图像中的物体实际上在3D环境中的位置:
两个人其实差不多高,只是房间构造和人物距离的设定使得成像后有视觉误差,具体可以看GAMES101课程的内容。(鸽子为什么会这么大?)
由于矩阵运算在多维场景下更方便,我们不妨将上述公式以矩阵形式表达:
我们将原先的2维坐标和3维坐标都以齐次坐标形式进行表示,故两者的换算关系现在变成下面这样:
进一步:
到这里,我们就知道了3D牛牛的一个坐标[X,Y,Z]在已知相机焦距f的情况下,是如何转换到2D牛牛的,即乘上一个叫做Projection矩阵的玩意,太简单辣!
当然,这时候你可能会奇怪,这个[x,y,w]中的w是怎么来的?其实[x,y,1]坐标在同时乘或除上一个系数时,该坐标保持不变,比如[xw,yw,w]
、[x/w,y/w,1/w]
和[x,y,1]
都是表示一个点:
所以为了通用性和后续处理,就写成[x,y,w]。
上述我们说到,3D物体到2D成像,需要用到世界坐标到图像坐标的转换公式,中间会乘一个叫透视矩阵的玩意,该玩意其实也有多种表达形式,看你怎么方便怎么来:
但现在问题来了,我们推一个公式要尽量符合通用性,比如我们上面就将[x,y,1]换成了[x,y,w]。
但是我们的公式仍然有不足之处,比如该公式只能满足相机平面在中心的情况:
但是了解过图像实际存储格式的人应该清楚,比如像numpy等定义的矩阵,其坐标原点是在左上/下角而不是在中心的,上述所说的公式用不了。
故我们再进一步推导:
假设我们的图像中心是在图像某个角落,距离图像中心为p
,那我们只要在Projection矩阵里加上一个中心到该角落的位移值(px
,py
)即可。(详细部分可以看网上的物体矩阵旋转、位移换算资料)。
上面我们讲述了如何将3D环境中的物体投影到任意坐标系的图像平面,接下来我们再进一步讲述一些常用的概念。
我们可以将我们推导出来的Projection矩阵拆成以下两个部分:
为什么要拆呢?因为原先的矩阵第四列全是0,属于没用的信息,我们要只关注有用的信息。
这个K就是我们经常在各个摄像机规格书或数据集看到的相机内参矩阵(Intrinsic Matrix),其是一个3x3的矩阵,对角线有该相机焦距信息,并在最后一列有着像素偏移量。
更新中…