• 3D点云数据集制作实录【LiDAR】


    在过去的两年里,我一直在和机器人打交道。 今年早些时候,我不再只关注相机,而是决定开始使用激光雷达。 因此,经过大量研究后,我选择了 32 束 RoboSense 设备。
    在这里插入图片描述

    推荐:用 NSDT编辑器 快速搭建可编程3D场景

    我不得不花一些时间来设置它,特别是创建一个合适的支架,也可以携带相机。 经过一番尝试,激光雷达终于准备好了,我宣布我爱上了这种数据。

    我项目的下一步是开始开发一个系统,使用 LiDAR 点云检测和跟踪 3D 对象。 应用程序多种多样,但包括检测固定物体(建筑物、交通标志等)以创建 3D 地图,以及检测移动物体(行人、汽车等)以避免碰撞。

    在开发上述任何应用程序之前,我首先需要学习如何有效地将点云数据加载到 TensorFlow(我用于深度学习的工具)中。 目前,我的数据集由 12,200 个点云图像对组成。 该图像用作背景来了解激光雷达正在观察什么。 我还对所有点云进行了预处理,以仅显示大约在相机视野内的数据,而不是原始的 360° 视图。
    在这里插入图片描述

    尝试将数据加载到 TensorFlow 比我预想的更具挑战性。 首先,点云存储为 PCD(点云数据)文件,这是一种用于存储 3D 点云数据的文件格式。 TensorFlow 无法直接处理这种类型的文件,因此需要进行转换。 Open3D 库是一个易于使用的点云操作工具。 使用此工具,我可以轻松加载 PCD 文件并将点提取为 X、Y 和 Z 坐标的 NumPy 数组。 另一个工具 NSDT 3DConvert用于可视化PCD点云并确认在 Google Colab 上正确提取了点:
    在这里插入图片描述

    https://3dconvert.nsdt.cloud

    有了新工具,我将 12,200 个 PCD 和 12,200 个 JPG 上传到我的 Google Drive,并将其连接到 Google Colab。 然后,我创建了一些代码来加载 PCD、提取点并将它们放入 NumPy 数组中,这是 TensorFlow 可以轻松处理的结构。 我自信地运行了代码,并惊恐地看到,等待几分钟后,Colab 抱怨在转换点云时内存不足。 坏消息,因为我计划收集和处理比目前更多的数据。

    幸运的是,这是处理大型数据集时的常见问题,而 TensorFlow 等工具具有处理此类情况的功能。 所需的解决方案是 Dataset API,它提供了创建高效输入管道的方法。 引用API的文档:数据集的使用遵循一个常见的模式:

    • 根据你的输入数据创建源数据集。
    • 应用数据集转换来预处理数据。
    • 迭代数据集并处理元素。
    • 迭代以流式传输的方式进行,因此完整的数据集不需要装入内存。

    因此,本质上,Dataset API 将允许我创建一个管道,并且数据将根据 TensorFlow 中的训练循环的请求分部分加载,从而避免内存不足。 因此,我回顾了如何使用 API,并创建了一些代码来构建数据管道。 按照上述模式的步骤 1,代码首先加载所有 PCD 和图像的 URL 列表,然后在步骤 2 中,加载 PCD 并将其转换为 NumPy 中的点,然后加载图像并对其进行标准化。 但这时候我又遇到了麻烦。

    为了提高效率,Dataset API 中的所有内容(显然还有所有 TensorFlow API)都作为图中的张量运行。 Dataset API 提供了从不同格式加载数据的函数,但没有用于 PCD 的函数。 在研究了不同的可能解决方案后,我决定不再将数据作为多个 PCD 和 JPEG 文件并让 TensorFlow 加载并预处理它们,而是离线预处理所有数据,并将其打包到 HDF5 文件中 。

    HDF5 是一种开源文件格式,支持大型、复杂、异构数据。 我显然已经验证了 Dataset API 支持这种类型的文件。 使用这种格式的主要优点除了可以很好地使用 TensorFlow 之外,还在于我可以将所有数据打包到一个结构良好的大文件中,以便我可以轻松移动。 我创建了一个简单的 Python 脚本来加载所有 PCD、提取点,并将它们与相应的上下文文件一起打包到一个漂亮的 HDF5 文件中。

    def generate_hdf5_dataset_with_padding(path, run_name, hdf5_filename):
    
    	# Build main path
    	path = join(path, run_name)
    	
    	# Get files
    	jpgs = sorted(glob.glob(path+"/jpg/*.jpg"))
    	pcds = sorted(glob.glob(path+"/pcd/*.pcd"))
    
    	# Open HDF5 file in write mode
    	with h5py.File(hdf5_filename, 'w') as f:
    		
    		images = []
    		point_clouds = []
    		
    		# Determine the size of largest point cloud for padding
    		max_size = 0
    
    		for i, jpg in enumerate(jpgs):
    
    			base_name = jpg[jpg.rfind("/")+1:jpg.find(".jpg")]
    
    			# Load the image
    			image = cv2.cvtColor(cv2.imread(jpgs[i]), cv2.COLOR_BGR2RGB) 
    			images.append(image)
    
    		
    			# Load the point cloud
    			cloud = o3d.io.read_point_cloud(pcds[i])
    			points= np.asarray(cloud.points)
    			point_clouds.append(points)
    			
    			# Keep track of largest size
    			if points.shape[0] > max_size:
    				max_size = points.shape[0]
    			
    			if ((i+1) % 1000 == 0):
    				print("Processed ",(i+1)," pairs of files.")
    				
    		print("Max size ", max_size)
    		print("Padding ...")
    
    		# Pad the point clouds with 0s
    		padded_point_clouds = []
    		for points in point_clouds:
    			pad_amount = max_size - points.shape[0]
    			
    			points_padded = np.pad(points, ((0, pad_amount),(0, 0)), 'constant', constant_values=(0, 0))
    			padded_point_clouds.append(points_padded)
    
    		# Create an images and a point clouds dataset in the file
    		f.create_dataset("images", data = np.asarray(images))
    		f.create_dataset("point_clouds", data = np.asarray(padded_point_clouds))
    		
    	print("Done!")
    
    • 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
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    将 HDF5 文件(约 18 GB)加载到我的 Drive 中后,我返回 Colab 并添加相应的数据集 API 代码。 本质上,该模式的第 1 步从 HDF5 文件加载图像和点并创建相应的对,第 2 步从点云中随机选择一些点(我将在后面的文章中解释原因),并对图像进行归一化, 步骤 3 已准备好根据请求很好地提供数据。

    def resize_and_format_data(points, image):
    
      # Sample a random number of points
      idxs = tf.range(tf.shape(points)[0])
      ridxs = tf.random.shuffle(idxs)[:SAMPLE_SIZE]
      points = tf.gather(points, ridxs)
    
      # Normalize pixels in the input image
      image = tf.cast(image, dtype=tf.float32)
      image = image/127.5
      image -= 1
      
      return points, image
    
    def get_training_dataset(hdf5_path):
      # Get the point clouds
      x_train = tfio.IODataset.from_hdf5(hdf5_path, dataset='/point_clouds')
      # Get the images
      y_train = tfio.IODataset.from_hdf5(hdf5_path, dataset='/images')
      # Zip them to create pairs
      training_dataset = tf.data.Dataset.zip((x_train,y_train))
      # Apply the data transformations
      training_dataset = training_dataset.map(resize_and_format_data)
      
      # Shuffle, prepare batches, etc ...
      training_dataset = training_dataset.shuffle(100, reshuffle_each_iteration=True)
      training_dataset = training_dataset.batch(BATCH_SIZE)
      training_dataset = training_dataset.repeat()
      training_dataset = training_dataset.prefetch(-1)
    
      # Return dataset
      return training_dataset
    
    • 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

    我使用非常基本的训练代码尝试了数据管道,效果非常好。 不再出现内存不足错误。 我不确定这是否是提供数据的最有效方法,但它确实成功了,特别是,创建管道是点云数据操作的第一个很好的练习。 接下来,使用点云训练第一个 TensorFlow 模型。


    原文链接:制作3D点云数据集 — BimAnt

  • 相关阅读:
    二、数据仓库详细介绍
    crane:字典项与关联数据处理的新思路
    linux修改网关文件
    【0141】【创建postgres后端进程】postgres进程process title的设计机制(10)
    解析大型语言模型的训练、微调和推理的运行时性能
    1100w播放、45w涨粉!黑马UP在B站20天逆袭登顶!
    Windows中实现将bat或exe文件作为服务_且实现命令行安装、配置、启动、删除服务
    PMP每日一练 | 考试不迷路-11.22(包含敏捷+多选)
    操作系统实现-中断及任务调度
    sql面试
  • 原文地址:https://blog.csdn.net/shebao3333/article/details/133301550