打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

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

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

买的还是太贵了,如果可以自己开发一个,不需要太复杂的,那么以后做游戏就可以方便很多不用辛辛苦苦的从头建模了。或者如果可以扫描人体的话更加是大大减轻负担,降低成本。有没有算法之类的?
高一高二的时候用了一年半设计过一套手持3D扫描系统,有数学模型和论文,还有数据处理软件。

下面贴点自己的设计呗~~ 之前还没有怎么宣传过,不混开源社区,其实做得不算非常完美毕竟是个人项目嘛,摸爬滚打
————————多图预警——————
V1.0图片(转盘式)
V1.0图片(转盘式)


V2.0图片(手持激光线扫描)
V2.0图片(手持激光线扫描)

————————分割线————————

整个系统的一个总体思路是渲染的逆向工程

之前在论文里写了关于可变焦3D扫描的研究,包括物理设计与数学实现,已完成的部分的物理和编程实现。其主要流程是,在较暗环境中,用激光线(结构光)进行照射与拍照后要对数据进行处理。主要处理流程包括:

(1)对图片的采样计算获取2D点;

(2)从2D信息中生成3D顶点;

(3)标识点的识别分析并计算出当前照片相机的部分刚体变换信息;

(4)坐标变换;

(5)网格重构 。

运用了光学规律与定律、传统几何、线性代数、计算机三维图形学理论等来设计了一个从现实世界的物体转化为3D数字模型文件的系统,在理论上已经实现了一个手持、可变焦的3D扫描仪。物理实现上主要的传感器仅为重力传感器。


所以其实设计上,只用了单反,红色激光笔,重力传感器,还有一个标识结构。


外国在理论和实物上已有比较成熟的发展。其中已发展出了民用的扫描仪,美国3D打印机厂商MakerBot CEO布瑞·佩蒂斯(Bre Pettis)在SXSW互动大会上展示了3D扫描仪的原型品Digitizer.此扫描仪的价格在1800美元左右,但这个是转盘式的扫描仪,虽然没有 手持扫描仪的方便,而且表面信息容易获取不全,但是和国内四五位数的价格比起有着较大的优势。而且相对与转盘式等扫描仪,手持扫描仪因为其更为一般化的算 法和技术,价格也是异常昂贵。


所以了喔= =想着自己开发玩玩。试一下嘛学学东西。


然后就一发不可收拾了。


我是做过两个版本的,V1.0是物体放在转盘式上扫描,这样会容易产生盲区,因为有些地方是拍不到而且是激光照不到的。停滞了一段时间学线性代数和计算机三维图形学之后,再继续开发第二版。


不说废话了。



一、局部空间(Local Space)

无论是哪个版本,第一个任务就是升维。但是很多人就会觉得奇怪,为什么从一张二维的图片可以凭空生成三维的坐标???嗯嗯嗯确实不可以凭空生成三维点,因为信息丢失了就不可能再找回来了。所以要生成一个三维点就需要更多的信息。


第一步,就是要生成局部坐标。我们这里定义的局部坐标,就是在相机参考系内,或者说,站在观察者的角度看问题测出来的坐标。一步步来嘛


来讲讲我设计的扫描结构(感觉市面也有类似的,有点启发的)。看俯视图,先要一台单反(其他也可以,我家刚好有单反,还能顺便做变焦扫描仪,平衡了扫描尺寸和精度的矛盾),然后放红色激光,在激光头的出口处摆一个玻璃柱,让激光线变为激光面(可以在墙上投出一条竖线),而且激光面平行于主光轴,一开始的时候是垂直于地面

下面是侧视图。



所以我设计就是激光面到主光轴的距离是确定而且是已知的,记为CamToLight,单位mm。

我们还要知道相机的参数如视场角,拍照的像素尺寸




事实上,照在墙上是直直的一条激光线,照在凹凸不平的物体上就不是了,起码在照片里面不是。
上图就是了,一条激光线,照到盒子上,拍照,pia,分成了两条。为什么会这样??怎么定量分析???



计算机图形学里有一个概念叫视截体,这是非广角Camera的一种理想模型
这说明了相机是进行透视投影成像的。

所以我们可以根据这个继续下去。

看俯视图。
AB:主光轴所在直线上的线段,之后延伸为光心到虚拟背景板的距离,命名为“标准深度”(Standard Depth,瞎编)。实验证明这个量无物理意义,这个“标准深度”,即到虚拟(假想)背景板的距离,是可正可负的,所谓的背景板只是选用一种标准,是想象出来的,无论是否有真实的背景板。实际上采用多远的背景板,测量点到光心的距离都是不变的,变的只是测量的深度。
DF=BC:红激光线到主光轴的距离
CD:物体到背景板的距离,命名为深度
GH:视截面的长度,D在此视截面上。
IJ: 视截面的长度,C在此视截面上。
∠JIA:记作∠θ,可视角范围

然后我们把目光从世界空间转到屏幕空间。要结合成像才能推出公式。
P预:“基准线”在屏幕上的X坐标,这个基准线与图片横边垂直平分线的距离,与上文提到的“标准深度”有关,原因显而易见。
P实:实际成像点在屏幕上的X坐标
PictureHeight:照片纵向像素数
PictureWidth:照片横向像素数


算法基本思想(由偏移得高度):照片上偏移的比例等于实际偏移的比例



我们把上面公式编程成函数,名字叫GetDepthFromOffset(自己瞎编)。这条公式是第一部分的基础,作用是根据紅激光在成像上的偏移测出它到 ”背景板“的距离,相当于Z坐标。再结合成像的xy坐标,我们就可以算出坐标的xyz分量。(用左手系,y轴指向天,z轴往前插,x轴向右)


但是,xyz的实际三维坐标(局部空间)中还是要计算的。


LocalX:绝对值为CamToLight,符号由激光在主光轴的左右边决定。摄像机正交基x轴正方向朝着视角的右边,z轴是视向量。


LocalY:

实际上,Local Y坐标还和LocalZ坐标有关,所以实际计算的时候是先要计算Z坐标的。如图,


EF :长度为R,某一视截面的实际高度,方便起见我们还假设EF就是背景板
A:物体上的一个可视点
OB :标准深度,焦点到背景板的距离
AC:测得深度,值为z
ED/EF:这是一个比值,值为k,可以根据成像获得,即 (屏幕上端到A点成像的距离) / (屏幕高度),这个应该要用像素数去计算。
d:标准深度
z:到背景板的距离



LocalZ:值为StandardDepth - GetDepthFromOffset 。


事实上到这里,我们已经可以生成图像中像素点的局部三维坐标了。






二、提取激光线,生成二维点


看图应该也差不多明白了呗=。=设定一个颜色阈值,对每一行像素进行遍历,寻找颜色转折点,得到激光线的像素坐标区间。我就简单地对区间取个平均值,从而提取出每一行像素上激光线的大致X坐标。





三、世界变换

在计算机三维图形学里,有渲染流水线这一个说法(貌似叫render pipeline?)。在进行三角形渲染之前都要进行顶点变换(Vertex Transformation),有人叫这个是“顶点变换”三部曲,意思是通过WORLD,VIEW,PROJECTION三个矩阵把处于局部模型空间的 顶点转换到相机的正交投影空间,并且投影到“底片”上。这些东西偶像们 @Milo Yip@叛逆者 不知道是多少年前就在玩的。(我在想这个思路还是挺有趣的)
“渲染”(render)做的事是从三维数据生成图片。而3D扫描是一个逆向工程(Reverse Engineering),所以我们可以借鉴渲染管线,进行一个逆向变换,转到世界空间中。这个世界空间是唯一的确定的。
为什么要确定一个世界坐标系????因为我们拍的图片分析后生成的顶点只有相对于相机参考系(局部空间)而言的坐标,而且理论上每张图片相机的位置,姿态角都不一样,所以才要对每张图片的所有顶点进行对应的变换,整合到一个坐标系下。

假设我们知道相机的姿态角(用重力传感器测,用Yaw-Pitch-Roll角度系统),和世界坐标,我们就可以用一个仿射矩阵去实现变换。


用的是列向量,下标别太在意,和欧拉角混用一下。用这个刚体变换矩阵就可以实现顶点的整合。




四、标志点——光学解算,实现手持的重要一步


前面说:
假设我们知道相机的姿态角(用重力传感器测,用Yaw-Pitch-Roll角度系统),和世界坐标,我们就可以用一个仿射矩阵去实现变换。

其实有些量并不是那么好测。例如光心的世界坐标(就是相机位置),如果用加速度传感器,时间久了容易会有积累误差。(倒是我以前根本没想到,用加速度传感器可能可以用PID控制去减少误差,不过不是很会)。



所以那个时候设计了一个光学校正算法。基本思路是,充分利用已有的信息(图片中标志点的2D像素坐标,相机参数如视场角,重力传感器测出的俯仰角和翻滚 角)去除相机翻滚角和俯仰角的影响,预测出没有俯仰角和翻滚角时标志点的相对位置,从而得出相机的水平角(航向角)和世界坐标。
需要有的物理结构是一个正方形框框,四个顶点分别放置一个颜色的灯。理想状态如下:

利用灯光颜色就可以确定哪个点对应哪个点。但是有个缺点就是OABC四个点必须全部都拍到(而且我没考虑干扰,去噪,因为根本不会= =所以用3DSMAX渲染出理想图片之后反过来用我的软件处理)

我们可以定义O为世界坐标系原点,OB为世界X轴,OA为世界Y轴。

此标识结构的作用有几个:
1,提供成像信息用以计算摄像机等效光心(摄像机位置)的世界坐标;
2,提供信息重力传感器不能测得的水平角(航向角);



一开始我们要去除翻滚角影响。
不过实际上在屏幕空间旋转一下就校正好了~~= =爽(其实就是绕主光轴Z轴旋转一下)


接下来,我们利用图片上标志点的2D像素坐标在3D空间中引出一条“屏幕射线”(跟渲染引擎里的Picking射线类似)。
然后我们经过一系列巧妙的纠结,可以求出相机位置到两个标志点的距离。然后 向量+距离 就可以求出O,B两个点在这个空间下的局部坐标。绕X轴旋转一下便可以去除翻滚角影响。


在这个空间下,相机是相当于只有航向角的影响,在这你会知道相机到四个标志点OABC的相对坐标。所以简单的变换一下,绕Y轴旋转一下,对齐一下,就能得到相对坐标和航向角。

然后其实完整实现到这里就可以得到3D点云了。(不理会去噪这些问题= =)

(图像分析不大会,激光线提取的不好,加点其他误差,搞得有点噪点)




五、网格重构(Mesh Reconstruction)
额,这种三维散乱点云的重构是一个大课题。有成熟算法不过也看不懂T T。
我就说说的我的小想法= =适合拓补简单,就是球那样的结构,胖乎乎的点云。

先把顶点投影到单位球上

像世界地图那样展开。

到这个带边界平面上。


最后进行2D的Delaunay三角剖分,得到三角形数据和邻接数据,最后映射回三维空间。



六、曲面细分
呵呵我连重构都没搞好细什么分



七、计算相机视场角

这个工序在顺序上是应该在流程的第一步。单反做取景器真的是大土豪= =。那就顺便用上单反镜头可以变焦这个功能。

然而在编程上怎么实现呢= =???因为你又没有佳能厂商的支持,做不了一个实时更新视角或焦距到电脑的自动化系统。所以用了一个小hack,在jpg文件中提取"EXIF“信息,引用百度百科
Exif是一种图像文件格式,它的数据存储与JPEG格式是完全相同的。实际上Exif格式就是在JPEG格式头部插入了数码照片的信息,包括拍摄时的光圈快门白平衡ISO焦距、日期时间等各种和拍摄条件以及相机品牌、型号、色彩编码、拍摄时录制的声音以及GPS全球定位系统数据、缩略图等。
你看,有焦距!!然后就可以拿焦距来计算视角,之后就可以生成三维点,然后继续下去








***不过还是一言难尽,传了论文到百度网盘,无聊可以看看= =
3D扫描.pdf_免费高速下载

———————分割线——————
V2.0的扫描系统也是烂烂的,反而是V1.0我实现从扫描到打印(不过噪点还是多)。然而,

v2.0还没有集成自动化系统,别看我,我不会
(; ̄Д ̄)

在 开发算法和软件的时候都是用3dsmax渲染的理想图片来喂给我的程序处理。研究的时候在得不到正确的结果时真的是万分纠结,因为根本不知道是算法、还是 编程、还是实验数据、还是实验参数出了问题,可能是这里漏了个符号,那里居然没有用临时变量,局部Y坐标公式错了5次,标识点处理仰角的竖直边居然不平行 于屏幕竖直边,维基的欧拉角矩阵看得一头雾水,变换不对时又不知道是变换错了还是标识点识别错了或者是计算错了,实验时设定数据想当然想到一个以为和真实 情况等价的结构但是却并不等价......排错非常困难,当时也是够拼的。

编程,我都是用VB实现的呵呵呵呵呵呵呵呵,渲染引擎是支持vb的TrueVision3D。
纪念Vb时代:

高一做的游戏 还是VB党 心酸


————————————————————
那次去面对一堆Princeton,standford清华复旦的教授答辩真是免费好好地练了一把英语,虽然最后也有点跪在了英语上。第二天的清华的面试 也没有什么鸟用,成绩太差,教授们面面相觑。所以这个项目在升学上并没有什么鸟用,但是却让我学到了很多东西,很让我第一次接触到“学术”。 真心觉得科研是非常难的,而且很辛苦。所以我觉得我以后能做个工程师已经是非常满意了。

成绩不稳,高考跪惨了。今天录取短信发来了,靠着可怜的自招加分进了华南理工大学,也不错,起码不用出省= =
现在在做DirectX11的渲染引擎,不知道够不够能力T T。大学好好学吧。
收藏 · 没有帮助 · · 作者保留权利
James Zhu,SFKR
谢虎苏李渊黄小彪 等人赞同
楼上有个高中生DIY一个激光扫描仪确实把我吓到了
如果没有人指导的话,那种自学能力还是很nb的

不过题主问的是三维扫描仪,还想用在快速建模上,且希望结构简单点。
激光线扫描的一个大问题是需要有一个可靠的移动平台,否则测量的精度和分辨率就相当有限了。
还有一个常用、成熟、且对器材要求不高的方法是条纹投影。
整套系统只需要一个相机,一架投影仪,一台电脑(Rasberry Pi之类的作控制器也没问题)。
DIY爱好者电脑、相机肯定是有的,家里或者工作室可能也有投影仪,那就几乎零成本了。

如果不想单独买一个投影模块,可以考虑带投影功能的平板手机,或者教学用的投影仪也可以——对便携性没用要求的话,摆在桌子上用用。不光速度快,亮度也比mobile模块高。

相位解包络和三维重建的算法也比激光线扫描或者三角测量容易不少。
下面是TI买的一个微型投影仪,大概跟Android低端机的价位相仿,已经附带三维测量的流程了:
3D Machine Vision System Solutions

我用TI的这款DLP也DIY了一个扫描仪:
用了两架投影仪为的是消除大件物体的阴影(其实我是买了4架备用的。。。)
微型投影仪的投射距离、投影面积、投影分辨率其实都远远不如做ppt报告的常用投影仪,
所以节约这个零件的钱,其实效果更好。
走线很丑不要计较了,用来trigger相机和投影仪同步。

效果如下图
5x5mm的小零件, 100x70mm的常规大小的鼠标
伪彩色就是被测物体的高度。(消噪以及后期处理的部分还没做好)
标定后的X-Y分辨率10微米,Z(高度)分辨率50微米左右,目前有号称达到5微米分辨率的——不用操这个心了,DIY自己建模玩玩sub-mm也够了
收藏 · 没有帮助 · · 作者保留权利
左庆,向了悟人生前进
1.前几年有很多MVS(multi view stereo)的文章,就是你用相机绕着一个物体拍很多图像,以这些图像作为输入算出面片(或者密集点云)
比如
[1] A Comparison and Evaluation of Multi-View Stereo Reconstruction Algorithms,2006
[2] CMVS-PMVS pmoulon/CMVS-PMVS · GitHub

2.最近几年有很多基于kinect的建模,从理论上来说,应该是前面MVS的实时版本(个人见解,假设你拍摄几千万上万张图像,然后做成一个视频流,应该就很像kinect了),
[3] Efficient model-based 3D tracking of hand articulations using Kinect, 2011.

但是,上面说的两种方法我都没有看到非常好的结果(与三维扫描仪相比)

三维扫描仪大概长下面这样,它的原理应该和kinect类似,但是精度非常高,扫描的时候物体上面会看到一个红点,红点动的比较快,残影看上去是竖条的,扫一幅深度图需要几秒到几十秒。
@鸡哥给的设备看上去差不多,我们用的时候也是把物体放在台子上,扫一个面就旋转一点。
(这种三维扫描仪很贵,所以后来才出现了MVS这类的方法)
收藏 · 没有帮助 · · 作者保留权利
匿名用户
杨芮明chunhui jia朱草 等人赞同
搜索看到这个问题,楼上高中生厉害!
这里献丑,我本人大四毕业设计也是做了 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实现拟合,得到三角测距方程里面几个参数的实际值,比如基线长度,夹角之类的:
到此完全讲完了,最后是当时用MFC写的软件GUI,结果还是 low 爆了。。。gal game 什么的我可从来没听过



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.

收藏 · 没有帮助 · · 作者保留权利
庾金科,全栈进行时
镜子知乎用户、知乎用户 等人赞同
楼上的高中同学DIY 项目真的让我很崇拜啊。

我现在高考刚刚结束 ,我不是业内人士。看到感兴趣的我就过来了。
第一次回答问题。
以前尝试用opencv 做过一个实时对手的点云重建。
不过现在都有现成的方法。
关于3D重建这一类问题。
现在能做到,商用级别的普遍是使用结构光方法。
MS的Kinect ,Intel的 Realsense 就是采用的这种方法
他的工作原理就是让红外激光DOE光栅 后高比分束为成千上万的小光束,即通常我们所说的散斑,射在物体上。摄像头通过捕捉反射的红外散斑,交由处理器进行解码后可计算出物体的三维数据。
来看看Kinect 的组成

--图片侵权私信我!


这是红外摄像头拍摄到的 红外散斑图像




这是实物到点云的重建流程


Intructables上 也有很多DIY 3D扫描器的

这是用kinect做的 3d扫描器

EASY Kinect 3D Scanner!

还有用线性激光器做的3D扫描器

Make your own 3d scanner!



当然还可以直接用两张左右图直接 匹配出 3D深度图。
对摄像头进行calibration后得出畸变参数,就能用Opencv进行视觉匹配。

LEFT


Right

调用opencv的BM方法得到的深度图


还有另外一种简便快捷的方法。

前段时间 AutoDesk公司推出了普通用户的建模软件Autodesk 123D

只需要按照序列拍摄不同角度的物体就可以输出3D模型。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
如何把旧照片变成数码图片
【新提醒】3D扫描仪diy。
机载激光雷达技术
三维激光扫描技术在深坑岩壁精细勘测中的应用
三维激光扫描技术在土方量算中的应用研究
有哪些种类的三维扫描仪?
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服