图像处理课期中要写一个图像拼接程序.
这方面的技术当然已经很成熟了, 开源界最著名的当属hugin, 拼全景图效果非常好. 在学术界也已经不是难题了, Lowe在IJCV2007的一篇 Automatic Panoramic Image Stitching using Invariant Features 是一个完整的流程介绍. MSRA的Szeliski有过一本几十页的 Image Alignment and Stitching: A Tutorial, 也详细的介绍了图像拼接的众多方法. 我基本就照着Lowe, Szeliski的一堆论文的方法在搞.
首先是要找Feature. Image Stitching对Feature的要求不是特别高, 一些简单的Feature似乎就可以. 但根据老师的建议我还是写了一个SIFT. SIFT的一个比较全面的介绍应该是Lowe 在IJCV2004的一篇 Distinctive Image Features from Scale-Invariant Keypoints, 至今已有近2万引用orz.SIFT的大致步骤如下:
Scale-Space and DOG-Space
Scale-Space是个早已在用的技术. 简单来说就是对于一张图片, 把它resize成$n$种尺寸, 加$m$种不同尺度的 Gaussion Blur, 得到的$n\times m$张图就叫Scale-Space, 把它们再两两做差就得到DOG-Space. 不过之前看到过一本厚厚的书就叫什么CV中的Scale Space方法, 所以这应该只是一个粗浅的理解, 好像还有更高端的东西.
Keypoint
这时候, Lowe说, DOG-Space里的极值点基本上就是关键点了, 只要再做些小处理. 处理包括在局部计算一些偏移, 舍去一些不太好的点(对比度低, 在边缘上).
Orientation
SIFT是Rotation Invariant的. 实现这一点其实也比较直观, 就是在每个关键点处找一个主方向出来, 用相对角度作为Feature Descriptor. 最终的Descriptor就是在关键点周围找16个点, 每个点周围八个相对方向的梯度值. 是一个128-d的double vector.
Matching
Lowe也给了Matching的方法, 说用欧式距离是最好的. 另外还说如果最好与次好相差太小就不要了.
在两幅图的Feature匹配上之后, 要算一个转移矩阵出来, 大家都说用一个RANSAC 算法. 名字听上去好NB啊: Random Sample Consensus, 其实很SB..大致就是: 先随机取些匹配点, 把矩阵解出来, 看这个矩阵Match了多少个点. 嗯, 这没问题, 然后..再随机取些点, 再解出来, 再随机取点, 再解出来..最后用 最好的那个.....给这算法跪了.
但是只是这样做的话有一个问题: 如果摄像机是旋转拍摄, 变换矩阵是8参数的Homography, 图片一多, 就会拼成这样:
地上那条白线本来是一个圆的, 理想情况在全景图中它应该被拉直, 可是我们真的快要把它拼成了一个圆..这当然 是不行的, 再加上一两张图, 图片就会超大了= =.
这个地方纠结了好久, 最后的解决方法是, 在全景图拼接时, 把原图先warping到一个柱面上. 一开始还有点想不通, 后来我看到了 Stanford CS178的这个页面. 一个很直观的applet.
然后就可以拼全景图出来了, 只是拼出来的整个曲线会扭曲. 这个根本原因应该是照相时具体参数不知道, 所以比例, 角度什么的全是错的, warp到了错误的圆柱上. paper里的 Bundle Adjustment 不会搞,就自己yy了一个二分寻找最佳倾斜角的方法, 以把图片拉长为优化目标, 最后还真把图片给拉直了.
拉直了之后再做一些后处理, 在边界处做一些插值, 然后切成矩形, 图就拼好了~
后来开哥带我去拍了个外景:
把拼的图变换到极坐标上$(x, y) \rightarrow (\theta, r)$, 再对$r$进行一些非线性放缩, 就能拼一个西瓜出来了~(听说有软件也可以做?)
源代码及一个正式一点的报告在github
另外, 崔鹏老师的图像处理课十分不错, 上课内容不像很多课一样随随便便能在书里翻到.
而且讲的也都是挺精华挺注重理解的东西.
就像是Andrew Ng的机器学习给我的感觉一样, 想想并没有真的教特别多的知识, 但最精华的思想全部都包括了, 整个领域的big picture也有了.