上手
open3d主要用于三维对象绘制,为Python提供了非常友好的接口,而且封装了一些基础的点云处理算法,加之Intel维护给力,是Python中处理三维对象的首选模块。
安装很方便
pip install open3d
装完之后还是老规矩,请出斯坦福兔子刷一波成就感
import open3d as o3d
pcd = o3d.io.read_point_cloud("rabbit.pcd")
o3d.visualization.draw_geometries([pcd])
除了import之外,两行代码,第一行是读取本地点云文件rabbit.pcd ,第二步绘图,结果如下
此界面虽然只有点云,但可通过快捷键进行交互,除了点击拖动改变视角之外,还可通过正负号调节点的尺寸;Ctrl和正负号调节网格尺寸;方括号可用于调节视场角。
鼠标控制则很符合直觉,只需Shift、Ctrl然后加上鼠标左键来回拖动,只需试一下就会明白其操作机理,要比文字描述更直观。
对于常用快捷键,由于稍微嫌多,故列在下面
| 常规指令 |
---|
H | 会在命令行中打印英文版的帮助信息,包含快捷键信息 | Q/Esc | 退出窗口 | R | 重置视点 | N | 开关点云法线渲染 | S | 切换平滑着色和网格平面着色 | W | 开关网格线框 | B | 开关背面渲染 | I | 开关插值中的图像放大 | T | 在图像渲染之间切换:无拉伸/保持比例/自由拉伸 | P | 截屏 | D | 进行深度捕捉 | O | 捕获当前渲染设置 | L | 开关照明 |
数字键用于颜色控制,其中单独点击数设置点云颜色;Ctrl+数字设置网格颜色,Shift用于调用内置的伪彩映射
| 单独数字/Ctrl | Shift |
---|
0 | 默认 | 灰度 | 1 | 渲染点颜色 | JET颜色 | 2 | 颜色对应x坐标 | Summer颜色 | 3 | 颜色对应y坐标 | Winer颜色 | 4 | 颜色对应z坐标 | HOT颜色 | 9 | 正常颜色 | - |
几何变换
鼠标拖动点云的过程,其实对点云进行了空间变换,手段无外乎三种:平移、旋转和缩放。open3d 通过translate, rotation, scale 来实现这些功能。
下面就演示一下这三个函数
import copy
pcd0 = o3d.io.read_point_cloud("rabbit.pcd")
pcd1 = copy.deepcopy(pcd0).translate((20, 0, 0))
pcd1.paint_uniform_color([1, 0, 0])
pcd2 = copy.deepcopy(pcd0).translate((40, 0, 0))
pcd2.scale(0.5, center=pcd2.get_center())
pcd2.paint_uniform_color([0, 1, 1])
pcd3 = copy.deepcopy(pcd0).translate((0, -20, 0))
thEuler = pcd3.get_rotation_matrix_from_xyz((0,np.pi/2,0))
pcd3.rotate(thEuler)
pcd3.paint_uniform_color([0, 1, 0])
pcd4 = copy.deepcopy(pcd0).translate((20, -20, 0))
th = np.array([0, np.pi/3, 0]).T
thAxis = pcd4.get_rotation_matrix_from_axis_angle(th)
pcd4.rotate(thAxis)
pcd4.paint_uniform_color([0, 0, 1])
pcd5 = copy.deepcopy(pcd0).translate((40, -20, 0))
quart = np.array([0,0,0,1]).T
thQuart = pcd5.get_rotation_matrix_from_quaternion(quart)
pcd5.rotate(thQuart)
pcd5.paint_uniform_color([1, 0, 1])
pcds = [pcd0, pcd1, pcd2, pcd3, pcd4, pcd5]
o3d.visualization.draw_geometries(pcds)
效果如下
其中平移和缩放没什么好说的,对于旋转,需要知道欧拉角有三个分量,分别是横滚、俯仰以及航向,代表绕x、y、z轴旋转。
考虑一架正在飞行的飞机,以某一时刻前后为x轴、左右为y轴、上下为z轴。则航向角就是飞机前进方向偏离的角度;俯仰角就是飞机头尾姿态的俯仰;横滚角描述的就是飞机翅膀的摆动。
欧拉角用于描述静态角度是没问题的,但用于表示旋转时会导致万向节死锁,简单来说就是飞机的航向角变化90°之后,其横滚轴变成了俯仰轴,而四元数则没有这个顾虑。
设欧拉角为
(
ψ
,
θ
,
?
)
(\psi,\theta,\phi)
(ψ,θ,?),则四元数可表示为
Q
=
[
cos
?
(
ψ
/
2
)
0
0
sin
?
(
ψ
/
2
)
]
[
cos
?
(
θ
/
2
)
0
sin
?
(
θ
/
2
)
0
]
[
cos
?
(
?
/
2
)
sin
?
(
?
/
2
)
0
0
]
\bold{Q}=\begin{bmatrix} \cos(\psi/2)\\0\\0\\\sin(\psi/2) \end{bmatrix}\begin{bmatrix} \cos(\theta/2)&0&\sin(\theta/2)&0 \end{bmatrix}\begin{bmatrix} \cos(\phi/2)\\\sin(\phi/2)\\0\\0 \end{bmatrix}
Q=?
??cos(ψ/2)00sin(ψ/2)??
??[cos(θ/2)?0?sin(θ/2)?0?]?
??cos(?/2)sin(?/2)00??
??
曲面重建
尽管实现点云绘制已经十分炫酷了,但是毕竟不够真实。斯坦福兔子据说也是用3D扫描仪扫出来的,所以其原型必定不是离散的点,而是连续的面。
作为专业的点云处理模块,open3d提供了多种生成表面的方法。
Alpha Shapes算法
Alpha Shapes算法又叫滚球法,思想很简单,不妨先从二维着手来理解。
假设平面上有一群点,然后我手里有一个球,只要我这个球足够大,那么当这个球滚向这群点之后,就会把最外层的点的轮廓描绘出来,而不至于串入点集的内部。
将这种二维的滚圆法推广到三维,就是滚球法,在open3d中,提供了create_from_point_cloud_alpha_shape 函数,用以生成Alpha shapes,其中输入为点云和alpha参数。
将alpha分别设为0.3,0.6,0.9和1.2,得到结果为
绘图代码如下
tri = o3d.geometry.TriangleMesh
pcd = o3d.io.read_point_cloud("rabbit.pcd")
meshes = []
alpha = 0
for i in range(4):
alpha += 0.3
tmpPcd = copy.deepcopy(pcd0).translate((i*20, 0, 0))
mesh = tri.create_from_point_cloud_alpha_shape(tmpPcd, alpha)
mesh.compute_vertex_normals()
meshes.append(mesh)
o3d.visualization.draw_geometries(meshes, mesh_show_back_face=True)
在曲面生成过程中,命令行输出了生成的三角形个数
TriangleMesh with 31267 points and 83772 triangles.
TriangleMesh with 34591 points and 95546 triangles.
TriangleMesh with 32583 points and 82728 triangles.
TriangleMesh with 29041 points and 67944 triangles.
其他重建方法
BPA(Ball pivoting Algorithm)算法从翻译来说,是更加纯正的滚球法,其基本思路也是滚球,但不同于Alpha Shapes,BPA直接将落在滚球上的点连接起来,作为轮廓。
由于在open3d中调用这种方法需要先设置法向量,故而等到讲完法向量再做BPA的代码示例。
此外,open3d还提供了泊松表面重构算法,但理解泊松表面的过程,需要首先理解八叉树,故而讲完八叉树再行讲解。
|