用wurblpt仿真ToF传感器

WurblPT

最开始是从这篇论文Simulation of Time-of-Flight Sensors for Evaluation of Chip Layout Variants 入手的, WurblPT有一个example用来仿真这个论文里的例子.

仓库依赖tgd, 可以先把这个仓库tgd clone一下, 先编译这个

1
2
3
4
5
cd tgd
cmake -B build
cmake -B build -DCMAKE_INSTALL_PREFIX=$HOME/.local -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Release .
cd build
sudo checkinstall

值得注意的有两个地方:

  1. 一定要编译Release模式, Release模式跑起来真的快很多.
  2. 这种用源码编译的库我一般都放在自己的.local目录, 那样不容易污染系统环境.
  3. checkinstall安装可以方便后续卸载, 但就是需要用到管理员权限, 卸载的时候也是通过dpkg卸载. 在安装的时候要记得看清楚安装的库的名字.

安装完tgd之后就可以安装libwurblpt了, 安装的命令也是一样的.

1
2
3
4
cd wurblpt/libwurblpt
cmake -B build -DCMAKE_INSTALL_PREFIX=$HOME/.local -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Release .
cd build
sudo checkinstall

最后再编译wurblpt-tof-example, 然后就可以跑ToF的仿真了.

1
2
3
4
5
cd wurblpt/wurblpt-tof-example
cmake -B build -DCMAKE_INSTALL_PREFIX=$HOME/.local -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Release .
cd build
make
./wurblpt-tof-example

仿真生成的都是.tgd后缀的数据, 可以用qv查看, 这个我也是从仓库的issue看到的, wurblpt#1 我是通过flatpak安装的qv, 可以把要看的一个系列图片放在一个文件夹里, 然后用qv查看整个文件夹, 然后可以用方向键的左右来看每帧的结果.

1
flatpak run de.marlam.qv result

如何将距离像转换为三维点云视图? 这里 只说了可以用距离像生成, 但是没有说具体怎么做. 而且tgd格式在python里的支持不是很好, 没法直接读取. tgd格式可以转tiff格式:
比如像这样可以把resutl.tgd中通道0的数据转换称tiff格式.

1
tgd convert -c 0 result.tgd result.tiff

然后tiff格式的数据在python中就可以比较方便处理了. 利用open3d可以生成3D点云.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import tifffile as tiff
import open3d as o3d
import numpy as np
import matplotlib.pyplot as plt

Z = tiff.imread("out.tiff")
Z = 300 - Z * 100
x, y = np.meshgrid(np.arange(Z.shape[1]), np.arange(Z.shape[0])[::-1])

points = np.stack((x, y, Z), axis=-1).reshape(-1, 3)

norm = (Z - Z.min()) / (Z.max() + 50 - Z.min())
colors = plt.cm.jet(norm).reshape(-1, 4)[:, :3]

pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points)
pcd.colors = o3d.utility.Vector3dVector(colors)

min_bound = points.min(axis=0)
max_bound = points.max(axis=0)

bbox_points = np.array([
[min_bound[0], min_bound[1], min_bound[2]],
[max_bound[0], min_bound[1], min_bound[2]],
[max_bound[0], max_bound[1], min_bound[2]],
[min_bound[0], max_bound[1], min_bound[2]],
[min_bound[0], min_bound[1], max_bound[2]],
[max_bound[0], min_bound[1], max_bound[2]],
[max_bound[0], max_bound[1], max_bound[2]],
[min_bound[0], max_bound[1], max_bound[2]],
])

lines = [
[0,1],[1,2],[2,3],[3,0],
[4,5],[5,6],[6,7],[7,4],
[0,4],[1,5],[2,6],[3,7]
]

colors_lines = [[0,0,0] for _ in lines]

line_set = o3d.geometry.LineSet()
line_set.points = o3d.utility.Vector3dVector(bbox_points)
line_set.lines = o3d.utility.Vector2iVector(lines)
line_set.colors = o3d.utility.Vector3dVector(colors_lines)

render_option = o3d.visualization.RenderOption()
render_option.background_color = np.array([1.0, 1.0, 1.0])

o3d.visualization.draw_geometries([pcd, line_set])