您的位置首页生活百科

是否可以 DIY 一个 3D 扫描仪或者开源 3D 扫描项目?

是否可以 DIY 一个 3D 扫描仪或者开源 3D 扫描项目?

的有关信息介绍如下:

是否可以 DIY 一个 3D 扫描仪或者开源 3D 扫描项目?

搜索看到这个问题,楼上高中生厉害!

这里献丑,我本人大四毕业设计也是做了 3D 扫描仪, 当时受了csk大神[1] 的启迪,看到楼上也有人发,正好当时在学Opencv就跑去跟导师说我要做这个,死乞白赖借了个4000块的工业CCD跟一个精密光学旋台就开搞了。当时还没入计算机视觉这个坑,硬是从相机矩阵一点点开始啃,OpenCV 也是那时候接触的,还兴冲冲跑去学 MFC 妄图写个高大上的界面,直到后来硕士期间接触了QT....OMG。

当时做出来的系统是这样的:

系统框图(丑):

跟小同学的方案不同,我对于扫描角度的控制是通过精密电控旋台来实现的,就是上图里面3D扫描仪下边那个黑乎乎的铁坨子。 要实现步进扫描,首先要实现的一个功能就是,电脑上位机程序能够通过指令传输控制这东西的旋转角度,简单说就是电脑给出一个数字,旋台自动转动这么多角度。

结果等拿到那个价值6000大洋的精密旋台,发现原版的控制箱只提供手动的转动角参数输入,虽然提供了可电脑编程控制的RS232接口, 但到处都找不到接口协议说明书,打电话问原厂,厂家表示产品太旧早早就停产,估计设计的工程师有,但人家回家带孙子了。。。。

于是我还得自己做控制器,好在步进电机驱动也算是自动控制的基础科目了,懒得自己焊上淘宝买了驱动器,再加一个STM32最小系统板输出控制信号,用UART串口与笔记本通信,算是解决了这个问题。

控制箱长这样,老大一个,搞得大家都以为这个是扫描仪的本体:

为了滤掉环境光的干扰,镜头前得加窄带滤光片(固定圈是我拿药瓶盖一点点掏的,本科生做点东西真心寒酸, 右图是使用的线状激光器:

得到的光斑是这样的:

最后的扫描结果是这样的(已经过 remesh 插值,原本的point cloud 文件已经丢失了):

关于原理,那位小同学已经讲得很明白了,我们的方案都是属于基于 triangulation 的 structured light 扫描原理,就是根据线状光斑在相机平面成像的水平位置利用三角形几何相似来计算光斑实际位置到相机平面的距离, 这是当时论文的配图:

推算的公式是:

这个图只描述了当光斑处在相面水平中线的情况,因为实际是线状激光,所以其实还要考虑在相面y轴存在水平位移的情况,示意图如下:

与之对应的公式更复杂,就不放上来占版面了。

于是在相机拍下一张有线光斑的图像之后,在相机平面 x 方向的某行像素阵列上,图像灰度的分布会是这样的:

可以看到中间的那个大峰值就是光斑。 理论上最简单的提取光斑的位置的方法是找到一行中灰度值最大的那个像素位置,但这样由于像素位置的离散性,扫描结果的分辨率会受到影响。于是乎这里引入了亚像素光斑位置插值的思路,就是通过对灰度分布进行估计,来找到光斑峰值在单个像素里边的具体位置, 示意图大概是这样:

插值方法很多,有很多这方面的论文,最流行的方法是把光斑强度分布近似看做一个高斯分布,然后用这些离散的像素点去估计高斯分布的mean value。

最后是定标,虽然上面公式里面默认相机内参,扫描仪基线几何尺寸以及激光线与光轴的夹角都是已知的,但实际上这些需要靠实验来获取,一方面是为了精确,另一方面是有些量比如基线真实长度难以直接测量。

相机内参,用广大computer visioner 喜闻乐见的chess board calibration, 同时这一步也是为了得到校正相机镜头畸变的参数,matlab 就有实现此功能的toolbox:

然后就是用矫正好的相机对一系列标准距离上的被测平面进行测量,记录若干组 “实际位置—光斑位置“的采样数据,然后对这些数据用 least square minimization实现拟合,得到三角测距方程里面几个参数的实际值,比如基线长度,夹角之类的:

到此完全讲完了,GUI 用MFC写的

References:[1] CSK.Blog-自制低成本3D激光扫描测距仪(3D激光雷达),第二部分[2]K. Konolige, J. Augenbraun, N. Donaldson, C. Fiebig, and P. Shah, “A low-cost laser distance sensor”, in ICRA, Pasadena, 2008.[3]R. B. Fisher, D. K. Naidu, “A Comparison of Algorithms for Subpixel Peak Detection”, in BMVC , 1996.