看到一个自己喜欢的小玩意儿,把它放到一个黑乎乎的盒子里,过那么一会儿,你就能得到它的obj网格模型文件,然后开心地拿着它去3D打印,复刻一个,是不是想想都很香?
今天介绍的项目,就是自己DIY这么一台基于树莓派的激光扫描建模仪。
正文
项目通过线激光发射器和树莓派摄像头来实现计算机视觉数据采集。激光定位的角度与激光成 45 度倾斜,同时在物体的垂直切片上投射出一条明亮的红线。
摄像头检测切片到中心的距离并给出网格切片。物体在旋转托盘上慢慢的旋转,通过重复这个过程,直到扫描完整个物体。
最后生成的obj文件可以自动通过邮件的形式发送到使用者的收件箱中。
创作灵感
开始制作前,我做了一些基础研究。发现许多 3D 扫描仪都利用到了旋转平台,然后使用各种不同的传感器来测量距中心的距离,建立旋转模型。其中很多都使用了类似于 Kinect 的双摄像头。
偶然的机会,我发现了Yscanner,这是一种使用激光的低分辨率扫描仪。考虑到简单性和可行性,在这种激光技术中,激光相对于相机偏置照射来测量与中心的距离,看起来似乎还不错。
材料清单
树莓派 × 1
树莓派摄像头V2 × 1
LED × 1
电阻 × 1
电线 × 若干
3D 打印灯丝 × 若干
木板 × 1
M3 硬件 × 若干
步进电机 × 1
线激光发射器 × 1
LN298 步进电机驱动器 × 1
金属按钮 × 1
烙铁 × 1
激光切割机 × 1
3D 打印机 × 1
螺丝刀 × 1
钳子 × 1
设计原理
该项目设计的核心组件就是能够垂直投射在物体上的线激光发射器。通过树莓派摄像头来抓取投影,对它透视进行校正,然后在进行图像处理前过滤。在图像处理中,收集线的每个部分到物体中心的距离。
在径向坐标中,此图片将同时产生 r 和 z 的分量,然后通过将物体旋转得到新的切片来实现三维效果。
为了达到预想的效果,我使用树莓派作为中央计算单元。
首先,将树莓派与步进电机和电机驱动器连接。由外部 5V 电源供电并由树莓派的 GPIO 引脚控制。
然后,将线激光发射器连接到树莓派的 3.3V 线上,并将树莓派摄像头连接到摄像头的输入上。
最后,安装一个简单的下拉按钮和一个用来显示状态的 LED 来向用户展示系统当前所处的状态。具体如图二所示。
需要注意的地方:
1、将电子设备安装到由 T 型槽和 M3 硬件搭建的激光切割盒中。
将电子设备安装在激光切割盒中,并与T形槽和M3硬件结合在一起。
2、将电子设备隐藏在底部隔间中,盖子上放置旋转托盘,便于放置物品。这个盖子可以最大程度地减少外部光照射到系统中。(外部光可能在最终的扫描中产生干扰)
硬件部分
在开始3D打印之前,先用了 Autodesk Fusion 360 设计出 3D 外壳模型。总的来说,外壳设计很简单,一个盒子和带活页的盖子。
设备主要分为两层:电子设备层和主体层,两层之间有孔可供电线通过。
使用 Epilog Zing 40 W 激光切割机进行切割。如上图所示,外壳主要由主体层、电子设备层、两个盖子部件、前片、后片以及两个侧片组成。
在主体层上,有三个切口:一个用于安装步进电机,一个用于放置激光器的电线,另一个用于放置树莓派摄像头的软排线。
底座有安装孔,用来固定树莓派、面包板,还有一个较大的切口和电机驱动器的安装孔,以及用于放入步进电机的较大切口。外壳的盖子可以简单地卡在一起,形成一个类似三角形状的盖子,合页宽度为侧板孔的直径。
背板和其中一个侧板在侧面都有插槽,便于可以轻松访问树莓派的端口(HDMI、USB、以太网以及电源)。前板是一个简单的部分,可以利用手动钻孔,然后安装上按钮和 LED。
所有的零件通过M3硬件、T型接头和插槽连接在一起。这种方法非常牢固。组拼时可以使用M3螺钉将零件固定在一起。
因为速度和便捷性的优势,我们使用激光切割机来处理大部分组件。但是,由于3D几何形状在裁纸器上非常难创建,仍然不得不对其进行3D打印。
第一个组件是线激光发射器的支架。它将被安装在与摄像头视线成 45 度角的主体层上,并有一个孔,可将激光器牢牢固定住。
另外还需一个马达支架,因为马达的轴太长了。支架产生的摩擦力不妨碍激光切割的组件,并降低了电机连接的平面,使旋转平台与主体层齐平。
电子部分
该项目的硬件接线非常简单,只需要将电机、按钮、LED、激光器以及摄像头连接到树莓派。如上图所示。
首先,将电阻与每个引脚串联,以保护引脚。GPIO 的一个引脚专用于控制 LED,当设备准备好后,LED 会亮起,当设备运行时,它会使用 PWM 进行脉冲控制。
其次,将 GPIO 的另一个引脚连接到上拉按钮上,未按下按钮时为高电平,按下按钮时为低电平。
最后,用GPIO的四个引脚用来驱动步进电机。
由于项目中的电动机只需要一定程度上的步进而无需控制速度,我们选用了一款很简单的步进电动机驱动器(L298N)。该驱动器只是将控制线升压以馈入电动机的输入。
为了了解步进电机如何在非常低的水平上操作,我们同时参考了L298N数据表和Arduino库。步进电机有一个磁芯,磁芯上有交替极性的磁极。
使用四根线缠绕去控制两个电磁铁,这两个电磁铁分别为电动机中的每个相对的轴供电。通过切换轴的极性,就可以推动步进器。
了解完步进电机的工作原理,就能够更容易地控制步进电机。由于步进电机的最大电流约为 0.8A,超出了树莓派的供电能力,我们最后选用了5V电源而不是树莓派为步进电机供电。
软件部分
该项目的软件部分由四块组成:图像处理、电机控制、网格创建和嵌入式功能。
1、如图所示,随着系统启动 .bashrc 自动登录到树莓派并开始运行 python 代码。系统点亮状态灯,告知用户它已正确启动,并等待按下按钮。
2、用户可以放置要扫描的物品并合上盖子。按下按钮后,LED 会闪烁,告知用户设备正在工作。
设备将在图像处理和电机控制之间循环,直到旋转收集完物品的所有数据。最后,创建网格模型文件并通过电子邮件将文件发送到预设的电子邮箱。
3、设备可以重新启动循环,只需按一下按钮就可以执行另一次扫描。
图像处理
第一步是处理获取的图像,以便将存储在图像中的信息提取为可用于创建空间点阵列的形式。
首先拍摄了平台上物体的照片,以及由激光照射到盒子背面并分散后产生的所有背景噪点。
该图片的原始形式存在两个主要问题。一是拍摄物体的角度较高,二是背景噪点很大。视角的问题是第一个要考虑的,因为按原样使用照片将无法确定的物体一致高度。
如图二所示,倒置的 “L” 形的高度是一致的。但是,由于一侧比另一侧长,它们在最靠近观察者的边缘处的高度似乎不同。
为了解决此问题,我必须将图像中的工作空间从之前的梯形形状转换为矩形。为此,我使用了链接中提供的代码。
https://www.pyimagesearch.com/2014/08/25/4-point-opencv-getperspective-transform-example/
当给定一个图像和四个点时,该代码将在四个点之间裁剪图像并补偿转换裁剪后的图像。使用四个点来创建矩形,而不是之前的梯形形状。
下一个需要解决的问题是外部光形成的背景噪点和激光本身反射的光。我使用 OpenCV 的 inRange() 函数过滤光。我将阈值设置为仅在特定水平上拾取红光。
为了获得正确的值,设置了一个比较宽的阈值区间,在区间内不断提高阈值水平,直到唯一被拾取的光是来自扫描物体上的激光。
获得此图像后,我找到了每行中最亮的像素,得到了一条每行一个像素的线,它与激光线的最左侧相接。最后,将每个像素转换为 3D 空间中的顶点并存储在数组中,如网格创建部分所述。
电机控制
在成功处理单个图像以获取物体的切片之后,我还需要旋转物体获得不同角度的新照片。为此要控制好扫描物体平台下的步进电机。
我通过创建一个变量来跟踪电机的状态和细分控制四个电机的输入,这些是实现步进机功能的基础。
网格创建
要从所有处理的图像创建网格,我必须首先将处理的图像中的每个白色像素转换为 3D 空间中的顶点。我要收集具有圆柱对称性的单个对象切片,所以要收集圆柱的坐标。
图片的高度可以用 z 轴表示,到旋转台中心的距离可以用 R 轴表示,步进电机的旋转可以用 theta 轴表示。由于我将数据存储在圆柱坐标中,因此必须将每个顶点转换为笛卡尔坐标。
顶点创建好后,将它们存储在一个列表中。然后再将所述列表存储在另一个列表中,该列表包含为获取的每个图像创建的顶点列表。处理完所有图像并将其转换为顶点后,在最终网格中显示顶点。
其中,最好包含顶部顶点和底部顶点,然后根据分辨率,我选择了均匀分布的顶点数以用于每个图像。因为并非所有顶点列表的长度都相同,所以我不得不通过找到顶点数量最少的列表并将所有其他列表中的顶点移除,直到它们均等为止。
创建顶点列表后就可以创建网格。我使用 .obj 文件标准设置网格格式,因为它很简单并且支持 3D 打印。
嵌入式功能
当设备正常运行后,我通过添加完整的嵌入式功能对其进行了完善。这意味着移除键盘,鼠标和显示器,处理完成后以无线方式将.obj文件发送过去。
1、将.bashrc代码更改为自动登录并在启动时启动 python 主程序。执行sudo raspi-config命令,设置 “Console Autologin”,并将sudo python /home/pi/finalProject/FINAL.py行添加到/home/pi/.bashrc。
2、添加一个按钮和 LED 状态显示,用于用户输入和输出。按钮将会告知用户设备何时开始扫描,LED 将告诉用户机器的状态。
如果 LED 点亮,则表明设备已准备好开始扫描。如果 LED 闪烁,则表明设备当前正在扫描。如果 LED 报错,则表明软件错误,要求重启系统。
最后,我通过电子邮件向设备发送 .obj 文件。使用 smtplib 和 email 库来完成。这种无线的发送方式很方便,将生成的文件传送给用户,以便在许多不同的平台上访问。
组装
完成以上步骤后,现在可以将组件组合在一起。
在制造出设备的各种零件之后,我们可以把它们组装在一起。如上图所示:
1、组装外壳箱体。
2、将摄像头和激光器安装到盒子里。
3、安装其他电子设备。
4、树莓派的背面,可使用树莓派端口和 5V 电动机输入。
5、安装好设备正面以及带有 LED 状态指示灯的按钮。
完工!
激光 3D 扫描仪能够高精度地扫描物体。物体的特征清晰可变,并且使用切片软件(例如Repetier)可以很容易地对零件进行 3D 打印。
通过测试最大的惊喜是设备的一致性很好。在对同一物品进行多次试验中,即使稍微改了物品的位置,扫描程序也都能生成非常相似的 .obj 文件。
如上图所示,三次扫描的结果都非常的相似,能够获取到同样多的细节。系统的一致性非常不错。
可以调整的地方
可调整的变量之一是扫描的分辨率。因为步进器有 400 步,所以我可以选择每个 ΔΘ 来决定角度分辨率。在默认情况下,我将角度分辨率设置为 20 次迭代,这意味着电机每帧旋转 20 步(400/20=20)。
选择此项主要是为了节省时间,以这种方式完成扫描大约需要 45 秒。但是如果想要更高质量的扫描,就需要将迭代次数增加到 400。这为 3D 构造模型提供了更多的点,从而可以进行更详细的扫描。
除了角分辨率外,还可以调整垂直分辨率,或选择沿激光切片扫描多少个不同的点。为了节省时间,我将默认值设置为 20,如果你想得到更好的效果可以增加数值。
如图所示,通过改变角分辨率和空间分辨率的参数,可以显示出不同的扫描结果。每个标签的格式设置为角度分辨率x空间分辨率。从默认的扫描设置中可以看出鸭子的功能是可识别的,但并不明显。
但是,随着分辨率的提高,精确的功能开始显现出来,包括眼睛、嘴巴、尾巴和鸭子的翅膀。最高分辨率的图像大约需要 5 分钟扫描。高分辨率的效果是非常成功的。
不足的地方
尽管该项目取得了成功,但在设计和实施方面仍然存在一些局限性。随着激光的使用,光的散射带来了许多问题。我扫描的物体要么是半透明,很亮或者很暗的物体,它们在表面的反射就存在缺陷。如果物体是半透明的,光线就会被吸收并散射,从而使切片的读数非常不准确。在发亮和黑暗的物体中,光线要么被反射,要么被吸收,以至于难以收集。
此外,我使用摄像头获取物体的特征,就能感受到视线遮挡的限制,凹面的物体和锐角通常会被物体的其他部分阻挡。像示例中小黄鸭的尾巴在扫描中就失去曲率了。摄像头只能检测物体表面结构,无法获取孔或者内部为几何形状的物体。这一常见问题也在其他扫描机中存在。
可以优化的地方
虽然项目整体效果还不错,但还有可以优化的地方:
1、在当前状态下,只能通过更改代码中的硬编码分辨率变量来更改扫描分辨率。为了使项目更具嵌入式性,可以添加一个分辨率电位计,以便用户可以更改分辨率,而不用将监视器和键盘插入扫描仪。
2、扫描仪在创建时的图像效果不是很好。为了解决这个问题,可以使用网格平滑技术来平滑不规则和粗糙的拐角。
3、像素坐标不能很好地缩放到实际环境中。我创建的网格比实际物品大六到七倍。
责任编辑:彭菁
-
建模
+关注
关注
1文章
299浏览量
60731 -
激光扫描
+关注
关注
0文章
114浏览量
11425 -
树莓派
+关注
关注
116文章
1698浏览量
105520
原文标题:用树莓派做一个激光扫描建模仪
文章出处:【微信号:vision263com,微信公众号:新机器视觉】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论