很久没有在简书上面更新文章了,一方面是因为最近在实习,一些业务代码相关的笔记基本上整理在confluence上面。另一方面是最近相当长一段时间陷入实习+毕业论文双线作战的局面,整个人免不了有些焦虑和浮躁。
近期公司状况不是很稳定,本来实习签到3月11号就该结束了,权衡再三还是考虑先继续待下去。同时也希望能够多学习一些东西,在项目中发挥出一些价值。
近期主要在参与一个视线估计的项目,虽然整体来说我们采用的是appearance-based gaze estimation,直接通过deep CNN抽取输入ROI的feature回归出gaze的eular角度,但由于这种pose estimation本身属于SLAM领域(根据我们组leader的说法),项目过程中还是接触到了大量传统机器视觉的知识。这个过程中其实感觉收获还是挺大的,因为这一块确实有很多与数学紧密联系的内容,然后数学在CV中其实会给人一种solid的感觉,因为CV中的很多东西实在是让人感觉有点虚...
计算摄影学
我其实不太确定这个标题起的准不准。不过创建这个系列的目的就在于记录一些和相机相关的知识。比如相机的成像、坐标系的转换以及相机内外参的推导,然后到相关的应用,比如求解坐标系或者平面之间的转换矩阵等。
相机相关的知识有个很有意思的特点,就是每个人看到的时候都觉得似曾相识。无论是“世界坐标系、相机坐标系”这种看起来其貌不扬的术语,还是通篇涉及的矩阵转换,都很容易引起人们的错觉,就是“这不就是高中数学吗?我怎么可能不知道?”
OK,这部分内容确实大部分只需要用到高中数学的知识。但并不意味着每个人都了解。相反即便是一些工作一两年的图像算法工程师,对这块的了解程度也远远没有他以为的那么多。举个例子:
MATLAB中关于欧拉角和旋转矩阵相互转换的函数,是放在robotics toolbox下面的。除此以外,我在搜索一些角度转换问题时,偶尔还会进到一些ROS相关的页面。然后这个系列的很多笔记,都是从一本叫SLAM14讲的教材中获取的。
上面一段话的意思是说,相机模型相关的知识可能是多个学科(机器人、SLAM、图像处理)的基石,而并非你想象中的看一眼就会的东西。相比自欺欺人,大方地承认你对此一窍不通或许更有利于自己成长。事实上,菜鸟工程师们甚至很容易在区分yaw、pitch、roll时出洋相。比如我之前就因为在群里喊话时弄反了yaw和pitch,导致我们team leader把他头像换成了欧拉角示意图且保留至今...
关于态度
我写了很多废话,就是希望自己在工作和科研的过程中多一些敬畏心,自以为是,自欺欺人在行家眼里真的是憨批一样的存在。我的学习能力并不强,不懂的东西就应该老老实实加班,花一整块的时间来系统学习和联系,来换取熟练程度。
场景
之前在自动驾驶部门时就接触过坐标系转换以及投射变换相关的东西,但是由于种种原因没有深入学习。直到最近我在学习我司美国通用实验室大佬的代码时多次接触到,我才意识到,能够两次出现在两家独角兽企业项目中并且参与迭代数个月的内容,我终于到了不能再用“标定这些是工程的事情,和算法无关”欺骗自己的时候。
初体验——标定Homograpy矩阵
那时候我还在自动驾驶部门。一个天气晴朗的下午超哥他们带着一大堆雪糕筒,以及一脸懵逼的我到路测场地,完成一次Homography矩阵标定的数据采集。我们的工作很简单,就是将雪糕筒依次摆放到事先嵌入钉子的地面上。然后打开测试车的前视摄像头,在雪糕筒阵的正前方、左前方和右前方三个位置各录制几秒钟的数据。
我现在猜测之所以要录制三个位置,应该是由于前视当时使用了三个摄像头,互成一定角度。(最初感知过程中会对三个摄像头成像做stitch,得到一个角度很大的视野范围。)
由于事先嵌入钉子的位置确定,然后通过录制的前视数据可以计算出雪糕筒在前视摄像头平面的关键点坐标,这样实际上就得到了前视+俯视两个平面的一组匹配的点,即每个雪糕筒在前视、俯视图上的坐标已知。从前视平面转到俯视平面的转换属于刚性变换(rigid transform),即不允许形变/缩放,只允许平移和旋转,那么该转换将由旋转矩阵)和平移向量完全定义(和相关内容在后续章节记录)。由维度可知,和最多由12个未知数确定。故如果可以列出12个方程,即可求解出和进而确定转换矩阵。
根据对极几何约束(Slam14讲第七章给出证明),两个平面之间的转换关系可以由Homography矩阵完全确定。因此,假如可以获取9对以上两个平面上相匹配的点的坐标,理论上就可以通过9个方程组联立求出Homography矩阵的所有元素(实际上并不是通过方程组求解的,而是使用了H矩阵的一些其他特性,通过SVD分解求出的)。
这就是为什么我们要在已知俯视图中雪糕筒位置的情况下录制前视摄像头平面的雪糕筒数据。简单来说就是为了获取一组匹配的点的坐标,来计算Homography矩阵。
一旦H矩阵被计算出来,我们就可以利用它来实现前视摄像头场景到俯视场景的转换,一个简单的示例如下2图:
Fig. 2 通过Perspective Transform实现Scene Recovery
通过perspective transform,我们可以直接将前视摄像头检测到的目标(及各种感知结果)转换到俯视平面,这样做的一个重要意义在于获取了深度信息。
当然这中策略相对来说还是有些理想。因为实际无人驾驶过程中很难保证每时每刻车辆所处的路面倾角和采集场地一致,尤其是上下坡过程中,由于倾角差异过大,perspective transform的误差也会非常大。
深入体验——视线向量可视化
在真正接触这块之前,我很难想到自己连视线方向可视化都搞不出来。比如下面这张图,假如模型已经预测出了相机坐标系下的pitch/yaw,目前需要做的仅仅是将这个视线方向可视化出来。
Fig. 3 视线方向示意图
这个问题其实刚开始我发现自己看不懂转换公式时,觉得自己是个铁憨憨。不过后来随着参考的信息越来越多,反而觉得一开始看不懂也很正常。因为这块涉及到旋转的多种描述方法,以及严格的正方向包括初始方向的约束,尤其是需要准确地理解欧拉角的定义:即欧拉角不是一个绝对的角度而是一个旋转过程,这样才能理解欧拉角约定的顺序与恢复的顺序。
目标与展望
希望通过这个系列的记录,自己能够对相机相关的转换有一个扎实的掌握,进而可以对各种3D坐标系下camera相关的Transform或者Augmentation灵活运用,解决实际问题。
网友评论