已有工作
代码开源地址:https://github.com/PRBonn/lidar
在项目train/common/laserscan中定义了LaserScan类,其中定义的reset方法已经能够实现球面投影转换了,球面投影转换公式略。
代码实现
下面我们尝试自己来实现这部分代码:
首先我们需要获取.las文件的数据,这部分代码我们可以使用库laspy实现。
接下去我们需要获取las文件中每个点的三维坐标,并计算到当前位置的距离,代码中为(0,0,0)
x = las.X * las.header.scale[0] + las.header.offset[0]
y = las.Y * las.header.scale[1] + las.header.offset[1]
z = las.Z * las.header.scale[2] + las.header.offset[2]
再根据一些简单的数学计算得到方位角和仰角,并进行归一化。
# 计算range, azimuth, 和 elevation
range_ = np.sqrt(x**2 + y**2 + z**2) # 距离
azimuth = np.arctan2(y, x) # 方位角
elevation = np.arcsin(z / range_) # 仰角
# 将方位角归一化到 [0, 2*pi]
azimuth = (azimuth + np.pi) % (2 * np.pi)
# 归一化 elevation 到 [0, 1],可以调整范围
elevation = (elevation + np.pi / 2) / np.pi
接下来将数据映射到二维平面上,选择最近的点填入。
# 初始化range image,默认填充为无限大值
range_image = np.full((H, W), np.inf)
# 将range值填入range image中,选择最近的点
for i in range(len(range_)):
if range_image[v[i], u[i]] > range_[i]:
range_image[v[i], u[i]] = range_[i]
# 将无穷大的值替换为图像中的最大范围值
range_image[range_image == np.inf] = 0
最后进行可视化展示等,完整的代码如下:
import laspy
import numpy as np
import matplotlib.pyplot as plt
# 设置range image分辨率
H = 64 # 垂直分辨率
W = 1024 # 水平分辨率
# 读取LAS文件
las_file = "yourPointCloud.las"
las = laspy.read(las_file)
# 获取点的X, Y, Z坐标
x = las.X * las.header.scale[0] + las.header.offset[0]
y = las.Y * las.header.scale[1] + las.header.offset[1]
z = las.Z * las.header.scale[2] + las.header.offset[2]
# 计算range, azimuth, 和 elevation
range_ = np.sqrt(x**2 + y**2 + z**2) # 距离
azimuth = np.arctan2(y, x) # 方位角
elevation = np.arcsin(z / range_) # 仰角
# 将方位角归一化到 [0, 2*pi]
azimuth = (azimuth + np.pi) % (2 * np.pi)
# 归一化 elevation 到 [0, 1],可以调整范围
elevation = (elevation + np.pi / 2) / np.pi
# 将 azimuth 和 elevation 映射到图像坐标
u = (azimuth / (2 * np.pi) * W).astype(int) # 水平坐标
v = (elevation * H).astype(int) # 垂直坐标
# 初始化range image,默认填充为无限大值
range_image = np.full((H, W), np.inf)
# 将range值填入range image中,选择最近的点
for i in range(len(range_)):
if range_image[v[i], u[i]] > range_[i]:
range_image[v[i], u[i]] = range_[i]
# 将无穷大的值替换为图像中的最大范围值
range_image[range_image == np.inf] = 0
# 可视化range image
plt.figure(figsize=(10, 5))
# 使用热力图显示range image
plt.imshow(range_image, cmap='viridis') # 可以使用'gray', 'plasma', 'inferno'等其他色彩图
plt.colorbar(label='Range') # 添加颜色条,显示range值
plt.title("Range Image Visualization")
plt.xlabel("Azimuth (pixels)")
plt.ylabel("Elevation (pixels)")
plt.show()
# 如果需要,可以保存可视化图片
plt.imsave("range_image_visualization.png", range_image, cmap='viridis')
由于博主的数据是机载激光雷达数据,在尝试进行转换后发现效果并不好,故打算尝试其它点云数据分析方法。