imuncle.github.io
imuncle.github.io copied to clipboard
代码实现圆筒镜艺术
圆筒镜艺术是一门比较冷面的艺术,百度里搜索也找不到几张图片,不过大家一看就懂,比如下面这两幅图:


在我看来这种艺术的精妙之处在于得到的作品看似畸变无序,看不出是个什么玩意儿,但当把圆筒镜放上去的时候,相信所有人都会惊呼【卧槽】
然而我虽然热爱绘画,但我的绘画水平不行,所以我决定用代码的方式来绘制。
原理分析
直观来看,圆筒镜成像的过程如下所示:

但是这个没有揭示本质,实际的成像过程应该是下图所示:

可以把成像过程看为两步。图中O点为相机的聚焦点,①为相机的像平面,即我们期望在相机里看到的画面,②为①的纸张平面的透射变换,③为②对于圆筒镜的反射成像,③也就是我们最后要得到的图像。
透射变换
透射变换很简单,只需要求出纸张平面和相机像平面之间的单应矩阵即可,我这里直接使用相机标定中的棋盘,识别到角点后直接使用OpenCV的findHomography函数求得单应矩阵,这里用H表示,则两个坐标系之间的关系如下:

反射变换
反射变换则在纸张平面上分析,但因为圆筒镜的镜面是曲面,反射面法线方向都是改变的,所以我们首先要找到图像上每一点对应的法线方向,或者说对应的圆筒镜上的反射点。
如下图所示,我们可以根据相机像平面得到反射点,并且很容易知道,图像中同一列的像素点对应的反射点是一样的。

回到纸张平面,考虑一点(x, y),其反射点为(△x, -△y),反射成像点为(x', y')

通过简单的平面几何分析可以得到反射成像点的公式。

写成矩阵形式即为:

总结
至此,我们对成像过程的解析就完成了,用两个矩阵即可完全表示。我们只需要遍历每一个像素,对每一个像素依次做透射变换和反射变换即可。
最后给出我的效果:

1