11180| 3
|
[项目] diy 3D激光扫描仪 (转) |
这个东西网上以前也有,并不是我原创的,但是整个的制作过程都是我自己弄的,包括软件和硬件。算是借鉴了前人的创意吧。下面来详细说一下。 物体被放在一个旋转台上,通过摄像头捕捉照射到物体表面的激光线,通过对扫描线的处理得出该剖面的轮廓线。通过旋转台的旋转每间隔一个小的角度进行一次采样,最后得到足够多的表面轮廓线,就可以构建出物体的3D模型。 3D激光扫描仪原理 这个项目主要使用了三角测距法对距离进行测量。普通的三角测距原理如下图: 这个测距法得到的是目标点(P1和P2)距离Rotation Center的距离,但是在该扫描仪中,我定义了一个柱坐标系,该坐标系的原点是转盘中心,需要测量的距离也是物体表面距离中心轴的距离。因此,在本项目中,测距的原理图如下: 图中最上方“十”字就是旋转台中心,根据以上原理图,可以计算出r的值: (上式有误,勘误如下,20150511) 硬件部分 做好的扫描仪的硬件部分: 电路部分的连接如下图: 利用单片机驱动步进电机,步进电机带动旋转台,这样可以精确地控制旋转台的转速,得到更好的扫描效果。 实物连接如下: (忽略1602和摇杆,在这里没有用) Arduino在这里的功能并不重要,只是准确得驱动步进电机缓慢转动。硬件部分不是本文重点,不再敷述。 软件部分 单片机上的软件很简单,就是精确的控制步进电机的转速,因为这个摄像头的帧数很低(随便找个地方15块买的摄像头,估计没有更烂的了),只有10 fps,设定每隔2°扫描一次需要扫描180次,所以要扫描180个位置需要18秒,因此单片机控制步进电机每18秒旋转一圈就可以了。 视频捕捉和处理 从摄像头获取帧之后,查找出扫描线的位置,并根据开始得到的映射关系处理得到物体轮廓的正面投影 ,并利用向量把每个像素点坐标保存起来。 上图中右边是直接将原始画面二值化后得到的扫描线粗略位置(未经平滑处理),从图中可以看出,我已经利用中值算法查找出了扫描线的准确位置,并在图中用黑线表示出来。画面左侧,就是利用已经推导出的公式计算出的物体轮廓的正投影轮廓,但是这个轮廓线并不精确(未经平滑处理),并且夹杂着噪点。在所有数据采集完成之后,使用 函数去掉噪点并对扫描线进行平滑处理。 去除噪点的算法比较简单,遍历每一个点并计算其和周围4个点的距离,如果改点离周围的点足够远(我设置的是10个像素点),就可以认为这个点是孤立的,即为噪点,于是将其去除。 平滑算法有很多可以选择,但是我每一条扫描线上的采样点足够密集,达到480个点,即摄像头的纵向分辨率,因此直接采用了中值平滑,将每一条扫描线单独进行平滑处理后在根据其左右两边的两条线再进行平滑,如此反复10次得到了比较满意的效果。但是这样也有一点缺陷,使物体表面本来的小细节丢失了一些。但是这次实验中使用的摄像头成像质量很差,对物体表面的激光扫描线的捕捉不准确,使一些细节本身就无法捕捉到,这也造成了扫描线捕捉不准确,实属无赖之举。 这样一直采集到180条轮廓线后就得到了物体表面的信息,这些数据被称作“点云”。利用一个二维向量将点云数据保存起来。由于分辨率的问题,物理上的误差会在0.几毫米,并且如果不经过处理,最后得到的物体模型表面会变得很难看,下面就是表面经过处理和没经过处理得到的模型的对比: 绘制模型 点云用柱坐标表达,二维向量的两个角标分别表示了柱坐标的α和h值,其中保持的值为r。在数据采集和处理完成之后,就可以利用OpenGL进行模型绘制了。在绘制模型之前还需要把柱坐标转换成直角坐标。 在OpenGL中,绘制了三种模型:点云,线框,实体。其中,线框模型为了便于观察,可以改变线框的密集程度。 这部分并无特别之处,利用得到的点坐标,绘制出物。 工程已上传github,https://github.com/0x000000FF/3D_scaner 本项目转自 arduino 中文社区 http://www.arduino.cn/thread-4703-1-1.html |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed