SemanticKITTI 拼接语义点云帧

文章目录

    • KITTI
    • SemanticKITTI
        • Semantic Segmentation and Panoptic Segmentation
        • Semantic Scene Completion
    • 数据转换
    • 语义标签和点云拼接

KITTI

The odometry benchmark consists of 22 stereo sequences, saved in loss less png format: We provide 11 sequences (00-10) with ground truth trajectories for training and 11 sequences (11-21) without ground truth for evaluation. For this benchmark you may provide results using monocular or stereo visual odometry, laser-based SLAM or algorithms that combine visual and LIDAR information. The only restriction we impose is that your method is fully automatic (e.g., no manual loop-closure tagging is allowed) and that the same parameter set is used for all sequences. A development kit provides details about the data format.

  • Download odometry data set (grayscale, 22 GB)
  • Download odometry data set (color, 65 GB)
  • Download odometry data set (velodyne laser data, 80 GB)
  • Download odometry data set (calibration files, 1 MB)
  • Download odometry ground truth poses (4 MB)
  • Download odometry development kit (1 MB)

官网说了只有前十一个序列是用于训练的,所以里程计真实位姿转换矩阵在 ground_truth_poses 中只有前十一个序列的位姿转换。下载数据需要进行邮箱注册,等待审核,不过一般很快的……

SemanticKITTI

SemanticKITTI 在基于 KITTI 的基础上对车载激光雷达获取的点云数据进行了进一步的标注,用于三维目标识别检测以及场景点云补全任务,SemanticKITTI 和 KITTI 一样提供了比赛打榜的服务,各家可以拿自己的模型去评测 SemanticKITTI 任务。SemanticKITTI 提供了标注数据以供下载,标注数据不仅包含了 KITTI 的训练集当然也包含了 KITTI 的测试集(也即 11-21 十一个序列),不过这一部分的数据由于缺少真实的转换位姿,所以不能合成比较大的场景了,但是应该没什么关系因为 SemanticKITTI 的初衷就是做三维目标检测和分割的,原来的 KITTI 更多的是 SLAM 的数据集,做光流预测以及位姿估计的,用于自动驾驶任务方面的测评,那么序列的真实转换位姿当然不能给出来,不然大家就直接拿到测试集的真实地图了(但万一有人实地去测呢?)

Semantic Segmentation and Panoptic Segmentation

We only provide the label files and the remaining files must be downloaded from the KITTI Vision Benchmark. In particular, the following steps are needed to get the complete data:

  1. Download KITTI Odometry Benchmark Velodyne point clouds (80 GB)
  2. Download KITTI Odometry Benchmark calibration data (1 MB)
  3. Download SemanticKITTI label data (179 MB)
  4. Extract everything into the same folder. The folder structure inside the zip files of our labels matches the folder structure of the original data.
Semantic Scene Completion

Note: On August 24, 2020, we updated the data according to an issue with the voxelizer. Ensure that you have version 1.1 of the data!

We provide the voxel grids for learning and inference, which you must download to get the SemanticKITTI voxel data (700 MB). This archive contains the training (all files) and test data (only bin files). Refer to the development kit to see how to read our binary files.

We additionally provide all extracted data for the training set, which can be download here (3.3 GB). This does not contain the test bin files.

数据转换

See also our development kit for further information on the labels and the reading of the labels using Python. The development kit also provides tools for visualizing the point clouds.

SemanticKITTI 提供的官方的转换脚本仓库,但是我是在服务器上做实验,用不到数据可视化的功能,只想把目前主流的各个室外场景数据集(SemanticKITTI、Waymo、NuScenes)转换成 numpy 容易读取的 npy 或者 npz 格式文件,这样方便训练,统一了格式。可以 git clone 把仓库克隆到本地看看实际上是怎么做的,然后复制核心代码自己写一个转换脚本把 22 个序列都转换成带标签的 npz 文件。

SemanticKITTI 的转换脚本转换之前,数据集必须按如下方式排列组织:

/kitti/dataset/
          └── sequences/
                  ├── 00/
                  │   ├── poses.txt
                  │   ├── image_2/
                  │   ├── image_3/
                  │   ├── labels/
                  │   │     ├ 000000.label
                  │   │     └ 000001.label
                  |   ├── voxels/
                  |   |     ├ 000000.bin
                  |   |     ├ 000000.label
                  |   |     ├ 000000.occluded
                  |   |     ├ 000000.invalid
                  |   |     ├ 000001.bin
                  |   |     ├ 000001.label
                  |   |     ├ 000001.occluded
                  |   |     ├ 000001.invalid
                  │   └── velodyne/
                  │         ├ 000000.bin
                  │         └ 000001.bin
                  ├── 01/
                  ├── 02/
                  .
                  .
                  .
                  └── 21/

因为我打算自己写一个转换的 notebook ,所以就没必要提前把数据组织成指定的格式了,反正只要知道怎么把 label 文件中的数据和 velodyne 点云数据对应起来就行。我自己的目录组织是每个压缩包解压出来的数据分门别类放到各自的目录下:

┌[hm@hm 16:00:13] ~/datasets/SemanticKITTI
└> ls
total 7.1G
-rw-rw-r-- 1 hm hm 6.3G 5月   6 22:37 00.zip
drwxrwxr-x 3 hm hm 4.0K 6月   7 14:48 calib/
-rw-rw-r-- 1 hm hm 1.7K 5月  20 01:34 convert.ipynb
-rw-rw-r-- 1 hm hm 587K 5月   6 17:18 data_odometry_calib.zip
-rw-rw-r-- 1 hm hm 171M 5月   6 17:18 data_odometry_label.zip
-rw-rw-r-- 1 hm hm 1.3M 6月   7 15:59 data_odometry_poses.zip
-rw-rw-r-- 1 hm hm 662M 8月  24  2020 data_odometry_voxel.zip
drwxrwxr-x 3 hm hm 4.0K 6月  25  2019 label/
drwxrwxr-x 2 hm hm 4.0K 6月   7 16:00 numpy/
drwxrwxr-x 3 hm hm 4.0K 6月   6 21:14 point/
drwxrwxr-x 3 hm hm 4.0K 6月   7 15:59 poses/
drwxrwxr-x 3 hm hm 4.0K 6月   7 14:37 voxel/

语义标签和点云拼接

从 Semantic KITTI 开放的标签和 KITTI 开放的 velodyne 文件中提取点云以及语义标签然后通过 semantic_kitti.yaml 配置文件中的颜色标签映射做可视化。

这里关键的是不能直接使用 KITTI 对每个序列给出的 poses.txt 中的每一行的转移矩阵,因为这个矩阵是基于车载设备的左边第一个灰度相机的,而激光雷达的坐标系不是这个,需要根据 calib.txt 中给出的 Tr 行(左边的灰度相机到激光雷达的位置变换外参,前面四个 P1、P2、P3、P4 相机的内参,用于三维点云和二维像素的互相映射)

P0: 7.188560000000e+02 0.000000000000e+00 6.071928000000e+02 0.000000000000e+00 0.000000000000e+00 7.188560000000e+02 1.852157000000e+02 0.000000000000e+00 0.000000000000e+00 0.000000000000e+00 1.000000000000e+00 0.000000000000e+00
P1: 7.188560000000e+02 0.000000000000e+00 6.071928000000e+02 -3.861448000000e+02 0.000000000000e+00 7.188560000000e+02 1.852157000000e+02 0.000000000000e+00 0.000000000000e+00 0.000000000000e+00 1.000000000000e+00 0.000000000000e+00
P2: 7.188560000000e+02 0.000000000000e+00 6.071928000000e+02 4.538225000000e+01 0.000000000000e+00 7.188560000000e+02 1.852157000000e+02 -1.130887000000e-01 0.000000000000e+00 0.000000000000e+00 1.000000000000e+00 3.779761000000e-03
P3: 7.188560000000e+02 0.000000000000e+00 6.071928000000e+02 -3.372877000000e+02 0.000000000000e+00 7.188560000000e+02 1.852157000000e+02 2.369057000000e+00 0.000000000000e+00 0.000000000000e+00 1.000000000000e+00 4.915215000000e-03
Tr: 4.276802385584e-04 -9.999672484946e-01 -8.084491683471e-03 -1.198459927713e-02 -7.210626507497e-03 8.081198471645e-03 -9.999413164504e-01 -5.403984729748e-02 9.999738645903e-01 4.859485810390e-04 -7.206933692422e-03 -2.921968648686e-01

对于位姿文件的解析这里走了一些弯路,因为之前做过双目相机生成深度图然后再根据每一帧的相对位姿去拼接,这里想直接套用以前的老方法,发现拼接出来的结果很奇怪,之前我是这么解析 poses.txt 的每一行转成变换矩阵然后执行深度图点云的变换的:

# homogeneous 4x4 transformation matrix
# r11 r12 r13 tx
# r21 r22 r23 ty
# r31 r32 r33 tz
# 0   0   0   1
                
T = np.array([float(str_val) for str_val in gt_T.strip().split(' ')], dtype=np.float32).reshape((3, 4))
R = T[:3, :3]
t = T[:3,  3]
# raxis, angle_rad = resolve_axis_angle(R)
# angle_deg = angle_rad / np.pi * 180.0
# 从局部坐标系转换到相对一第一帧的世界坐标系,旋转+平移
points_list[:, :3] = points_list[:, :3] @ R.T + t

这里看了一下 SemanticKITTI 的 issues 看作者是怎么解释他们代码中用于提取每一帧点云的位姿变换矩阵的两个函数的:

def parse_calibration(filename):
    """ read calibration file with given filename

            Returns
            -------
            dict
                    Calibration matrices as 4x4 numpy arrays.
    """
    calib = {}

    calib_file = open(filename)
    for line in calib_file:
        key, content = line.strip().split(":")
        values = [float(v) for v in content.strip().split()]

        pose = np.zeros((4, 4))
        pose[0, 0:4] = values[0:4]
        pose[1, 0:4] = values[4:8]
        pose[2, 0:4] = values[8:12]
        pose[3, 3] = 1.0

        calib[key] = pose

    calib_file.close()

    return calib

def parse_poses(filename, calibration):
    """ read poses file with per-scan poses from given filename

            Returns
            -------
            list
                    list of poses as 4x4 numpy arrays.
    """
    file = open(filename)

    poses = []

    Tr = calibration["Tr"]
    Tr_inv = np.linalg.inv(Tr)

    for line in file:
        values = [float(v) for v in line.strip().split()]

        pose = np.zeros((4, 4))
        pose[0, 0:4] = values[0:4]
        pose[1, 0:4] = values[4:8]
        pose[2, 0:4] = values[8:12]
        pose[3, 3] = 1.0

        poses.append(np.matmul(Tr_inv, np.matmul(pose, Tr)))

    return poses

根据 issue 里作者提到的一些信息,也就是说 SemanticKITTI 的点云序列合成利用位姿的时候,还利用了 calib.txt 标定文件给出的几个相机的外参和内参,代码中用到了 Tr 外参把 poses.txt 中每一行代表的灰度相机相对于第一帧的变换矩阵转换成了基于激光雷达坐标系的相对变换矩阵。

那么现在就好办了,利用源代码给出的这两个转换函数生成正确的基于激光雷达的变换矩阵,然后再应用于每一帧点云就可以拼接了。

写一个 notebook 快速验证拼接的想法叭。首先需要的是从 .bin.label 文件中解析出原始点云数据和语义标签数据:

def parse_point_label(seq_id: int):
    lidars = np.fromfile(f"data/sequences/00/velodyne/{seq_id:06d}.bin", dtype=np.float32).reshape(-1, 4)
    points = np.ones(lidars.shape)
    points[:, :3] = lidars[:, :3]
    
    labels = np.fromfile(f"data/sequences/00/labels/{seq_id:06d}.label", dtype=np.uint32).reshape(-1)
    upper_half = labels >> 16      # get upper half for instances
    lower_half = labels & 0xFFFF   # get lower half for semantics
    
    return points, lower_half

def convert_colors(labels):
    colors = np.zeros((len(labels), 3))
    for i in range(len(colors)):
        colors[i] = np.array(palatte[labels[i]], dtype=np.float32)
    colors /= 255.0
    return colors

def transform(points: np.ndarray, pose: np.ndarray):
    # points [n, 4]
    # pose [4, 4]
    return np.matmul(pose, points.T).T

这里解析点云和语义标签都是直接照搬 semantic-kitti-api 仓库里的代码的,这个仓库如果只是做数据提取的话只用看 generate_sequential.py 就行了,从里面找相关的代码截取出来写 notebook 验证。我自己写的代码中数据集是通过软链接连接到当前目录下的,所以路径是写死的,大家可以根据自己实际情况替换函数中的读取目录路径。

然后就是指定要拼接哪些帧的点云:

calib = parse_calibration("data/sequences/00/calib.txt")
poses = parse_poses("data/sequences/00/poses.txt", calibration=calib)
# scan_file_list = sorted(f for f in os.listdir("data/point/sequences/00/velodyne") if f.endswith(".bin"))

scan_file_list = [
    0, 50, 100
]

concated_points = []
concated_colors = []

for scan_idx in scan_file_list:
    points, labels = parse_point_label(scan_idx)
    pose = poses[scan_idx]
    
    points = transform(points, pose)[:, :3]
    colors = convert_colors(labels)
    
    # np.savez(
    #     osp.join(output_dir, osp.splitext(scan_file_list[scan_idx])[0]+".npz"),
    #     points=points,
    #     labels=labels,
    #     pose=pose
    # )
    concated_points.append(points)
    concated_colors.append(colors)

points = np.concatenate(concated_points, axis=0)
colors = np.concatenate(concated_colors, axis=0)
ply = o3d.geometry.PointCloud()
ply.points = o3d.utility.Vector3dVector(points)
ply.colors = o3d.utility.Vector3dVector(colors)
o3d.io.write_point_cloud("output.ply", ply)

比如我这里以拼接 0、50、100 这三个序列帧为例,生成 .ply 文件可以在 MeshLab 中查看拼接可视化结果。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/707031.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

群体优化算法----多乌鸦搜寻算法介绍,找多目标函数组解,Pareto前沿

介绍 乌鸦搜寻算法(Crow Search Algorithm,CSA)是一种新型的群体智能优化算法,其灵感来源于乌鸦的行为特性,尤其是乌鸦在食物搜寻和藏匿过程中的智能行为。乌鸦是一种高度聪明的鸟类,它们展示出复杂的社会…

对补码的理解:两种求法

课本的结论是:二进制数的最高位是符号位。符号位为 0 表示正数和 零 ,符号位为 1 表示负数。 正数是原码反码补码都是一样的。负数的反码是:符号位不变,剩下位取反。 负数的补码是:符号位不变,剩下位取反&a…

eclipse创建maven项目

第一步:打开eclipse 我们选择java项目即可 点击finish即可 它会自动下载插件 然后在控制台上输入Y即可

ChatGPT:自然语言处理的新纪元与OpenAI的深度融合

随着人工智能技术的蓬勃发展,自然语言处理(NLP)领域取得了显著的进步。OpenAI作为这一领域的领军者,以其卓越的技术实力和创新能力,不断推动着NLP领域向前发展。其中ChatGPT作为OpenAI的重要成果更是在全球范围内引起了…

HAL库--内存保护(MPU)实验

MPU是内核外设,想获取相关资料只能从内核手册查找 MPU功能仅F7/H7系列具备 内存保护单元(MPU介绍) MPU基本介绍 说白了MPU用来管理内存和外设存储区的访问权限 MPU可配置保护8/16个内存区域(看芯片型号),每个区域最小要求256字节,且每个区…

C++ | Leetcode C++题解之第149题直线上最多的点数

题目&#xff1a; 题解&#xff1a; class Solution { public:int gcd(int a, int b) {return b ? gcd(b, a % b) : a;}int maxPoints(vector<vector<int>>& points) {int n points.size();if (n < 2) {return n;}int ret 0;for (int i 0; i < n; i…

阿里云运维第一步(监控):开箱即用的监控

作者&#xff1a;仲阳 这是云的时代&#xff0c;现在云计算已经在各行各业广泛的应用。但是上云对于大多数客户来说&#xff0c;依然有很大的学习成本&#xff0c;如下图仅是阿里云都有几百款产品&#xff0c;怎么选择&#xff1f;怎么用&#xff1f;对于客户来说都是问题。“…

高温车间降温通风方案

高温车间降温&#xff0c;解决厂房高温闷热必须做到以下两点才能实现&#xff0c;否则即使安装中央空调也没用&#xff1a;一、解决厂房内部热量 通过通排风负压风机、环保空调、工业大风扇等常用排热降温设备&#xff0c;降低室内温度&#xff1b;二、屏蔽外部太阳热源 …

5.0 Python 函数简介

1.函数 1.1 基本定义 定义: 将一组语句的集合通过函数进行封装, 简单来说是具有一定功能的代码容器, 想要执行这些语句, 只需要调用函数的名称即可. 特性: * 1. 可重复使用, 减少代码冗余. * 2. 组织结构清晰, 可读性增强. * 3. 可扩展性提高, 便于维护. 1.2 使用规则 函…

OpenCV学习(4.13) 霍夫变换

1.霍夫变换 霍夫变换&#xff08;Hough Transform&#xff09;是图像处理中的一种技术&#xff0c;主要用于检测图像中的直线、圆或其他形状。它通过将图像空间中的点映射到参数空间来实现&#xff0c;这样&#xff0c;图像空间中在同一直线上的点在参数空间中会形成一条曲线&…

CentOS系统自带Python2无法使用pip命令

Linux运维工具-ywtool 目录 一. 系统环境二.解决三.验证四.备注(1)输入"yum install -y python-pip",提示没有可用 python-pip包(2)安装完pip后进行升级 一. 系统环境 centos7系统自带的python2.7无法使用pip命令 二.解决 yum install python-pip -y三.验证 pip…

用PlayCanvas打造一个3D模型

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 基于 PlayCanvas 的 3D 物理场景开发 应用场景介绍 PlayCanvas 是一款功能强大的 3D 引擎&#xff0c;可用于创建各种类型的 3D 体验&#xff0c;包括游戏、模拟和交互式可视化。本技术博客将介绍如何使用 Pl…

【ARM Cache 及 MMU 系列文章 6.2 -- ARMv8/v9 如何读取 Cache 内部数据并对其进行解析?】

请阅读【ARM Cache 及 MMU/MPU 系列文章专栏导读】 及【嵌入式开发学习必备专栏】 文章目录 Direct access to internal memoryL1 cache encodingsL1 Cache Data 寄存器Cache 数据读取代码实现测试结果Direct access to internal memory 在ARMv8架构中,缓存(Cache)是用来加…

企业中的绩效管理

背景 企业中为何需要绩效管理&#xff0c;企业绩效管理为何比较难&#xff0c;这在企业管理中是非常难&#xff0c;同样也是非常有价值的命题&#xff0c;那么首先应该对这个命题有清晰的认知&#xff0c;特别是要想明白为何企业需要绩效管理&#xff0c;应该先明白企业。 企…

2024 年 19 种最佳大型语言模型

大型语言模型是 2023 年生成式人工智能热潮背后的推动力。然而&#xff0c;它们已经存在了一段时间了。 LLM是黑盒 AI 系统&#xff0c;它使用深度学习对超大数据集进行处理&#xff0c;以理解和生成新文本。现代 LLM 开始成型于 2014 年&#xff0c;当时一篇题为“通过联合学…

妙用OSGraph:发掘GitHub知识图谱上的开源故事

作者&#xff1a;范志东 1. 何为OSGraph&#xff1f; OSGraph (Open Source Graph) 是一个开源图谱关系洞察工具&#xff0c;基于GitHub开源数据全域图谱&#xff0c;实现开发者行为、项目社区生态的分析洞察。可以为开发者、项目Owner、开源布道师、社区运营等提供简洁直观的…

手机如何扫描拍照?方法分享

手机如何扫描拍照&#xff1f;在数字化时代&#xff0c;手机扫描拍照软件已经成为我们日常生活和工作中不可或缺的工具。无论是快速识别纸质文档&#xff0c;还是将照片中的文字转化为可编辑的文本&#xff0c;这些软件都为我们提供了极大的便利。然而&#xff0c;市面上的手机…

msvcp110.dll有什么解决方案,msvcp110.dll几种方法详细步骤教程

本文旨在探讨如何应对电脑出现 vcruntime140_1.dll 无法继续执行代码错误提示的问题。同时&#xff0c;将阐释该文件的作用&#xff0c;列举常见的错误问题&#xff0c;并提供一些在修复 vcruntime140_1.dll 时的注意事项&#xff0c;以避免在解决过程中引发其他问题。接下来&a…

【网络安全】【深度学习】【入侵检测】SDN模拟网络入侵攻击并检测,实时检测,深度学习【一】

文章目录 1. 前言2. Mininet 和 Ryu 的区别2.1 Mininet2.2 Ryu2.3 总结 3. 模拟攻击3.1 环境准备3.2 创建 Mininet 网络拓扑3.2 启动 Ryu 控制器3.3 模拟网络攻击3.4 捕获流量 4. 实时异常检测4.1 在 Ryu 控制器中4.2 在 h2 机器上的实验结果4.3 深度学习模型部署上h2机器 帮助…

如何获知lib cell的用途

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 除了databook可以查询cell的用途外&#xff0c;还可以通过在pr工具中获取lib cell属性的方法知晓其用途。 ICC2: report_attribute -app -class lib_cell SDFFXXX 通过看is_…