【点云】RandLA-Net Semantic3D SemanticKITTI 预测结果可视化

(1)将RandLA-Net的运行结果可视化

(2)将Semantic3D和SemanticKITTI可视化做对比

本文的代码的画图代码来自RandLA-Net的开源代码。实现部分为一些数据处理。

展示demo:https://www.bilibili.com/video/BV1MA411i7mo

# 师兄建议可以用pcl+放置相机和转角来实现,类似论文demo的那种效果。

目录

一、使用open3d画图

 二、SemanticKITTI绘图

三、Semantic3D绘图


一、使用open3d画图

主要是调用helper_tool.py中的Plot类,摘录如下。其中:

(1)random_colors输入为N,N是要表达的类别数,如SemanticKITTI是20类,Semantic3D是9类。

(2)draw_pc,输入x-y-z-r-g-b格式的数据绘图

(3)draw_pc_sem_ins,输入pc_xyz是点云坐标信息,pc_sem_ins是对应的label,plot_colors是label对应的颜色,SemanticKITTI中,每个序列、每帧中的label是不一定的,如果要使每个label对应的颜色相同,需要提前调用random_colors或自己生成,然后输入进去。

class Plot:
    @staticmethod
    def random_colors(N, bright=True, seed=0): # 生成随机颜色,其中N为需要的类别数
        brightness = 1.0 if bright else 0.7
        hsv = [(0.15 + i / float(N), 1, brightness) for i in range(N)]
        colors = list(map(lambda c: colorsys.hsv_to_rgb(*c), hsv))
        random.seed(seed)
        random.shuffle(colors)
        return colors

    @staticmethod
    def draw_pc(pc_xyzrgb): # 输入数据格式为x-y-z-r-g-b六维
        pc = open3d.PointCloud()
        pc.points = open3d.Vector3dVector(pc_xyzrgb[:, 0:3])
        if pc_xyzrgb.shape[1] == 3:
            open3d.draw_geometries([pc])
            return 0
        if np.max(pc_xyzrgb[:, 3:6]) > 20:  ## 0-255
            pc.colors = open3d.Vector3dVector(pc_xyzrgb[:, 3:6] / 255.)
        else:
            pc.colors = open3d.Vector3dVector(pc_xyzrgb[:, 3:6])
        open3d.draw_geometries([pc])
        return 0

    @staticmethod
    def draw_pc_sem_ins(pc_xyz, pc_sem_ins, plot_colors=None): # pc_xyz是坐标信息 pc_sem_ins是label plot_colors是用每类的颜色[r, g, b]/255
        """
        pc_xyz: 3D coordinates of point clouds
        pc_sem_ins: semantic or instance labels
        plot_colors: custom color list
        """
        if plot_colors is not None:
            ins_colors = plot_colors
        else:
            ins_colors = Plot.random_colors(len(np.unique(pc_sem_ins)) + 1, seed=2)

        ##############################
        sem_ins_labels = np.unique(pc_sem_ins)
        print(sem_ins_labels)
        sem_ins_bbox = []
        Y_colors = np.zeros((pc_sem_ins.shape[0], 3))
        for id, semins in enumerate(sem_ins_labels):
            valid_ind = np.argwhere(pc_sem_ins == semins)[:, 0]
            if semins <= -1:
                tp = [0, 0, 0]
            else:
                if plot_colors is not None:
                    tp = ins_colors[semins]
                else:
                    tp = ins_colors[id]

            Y_colors[valid_ind] = tp

            ### bbox
            valid_xyz = pc_xyz[valid_ind]

            xmin = np.min(valid_xyz[:, 0]);
            xmax = np.max(valid_xyz[:, 0])
            ymin = np.min(valid_xyz[:, 1]);
            ymax = np.max(valid_xyz[:, 1])
            zmin = np.min(valid_xyz[:, 2]);
            zmax = np.max(valid_xyz[:, 2])
            sem_ins_bbox.append(
                [[xmin, ymin, zmin], [xmax, ymax, zmax], [min(tp[0], 1.), min(tp[1], 1.), min(tp[2], 1.)]])

        Y_semins = np.concatenate([pc_xyz[:, 0:3], Y_colors], axis=-1)
        Plot.draw_pc(Y_semins)
        return Y_semins

 二、SemanticKITTI绘图

这里我是画序列11-21的第一帧,如果不想只画第一帧,将get_file_list和get_test_result_file_list中的break注释掉即可。绘制效果如下:

 

from helper_tool import Plot
from os.path import join, dirname, abspath
from helper_tool import DataProcessing as DP
import numpy as np
import os
import pickle
import yaml

def get_file_list(dataset_path):
    seq_list = np.sort(os.listdir(dataset_path))
    test_file_list = []
    for seq_id in seq_list:
        seq_path = join(dataset_path, seq_id)
        pc_path = join(seq_path, 'velodyne')
        if int(seq_id) >= 11:
            for f in np.sort(os.listdir(pc_path)):
                test_file_list.append([join(pc_path, f)])
                break
    test_file_list = np.concatenate(test_file_list, axis=0)
    return test_file_list

def get_test_result_file_list(dataset_path):
    seq_list = np.sort(os.listdir(dataset_path))
    test_result_file_list = []
    for seq_id in seq_list:
        seq_path = join(dataset_path, seq_id)
        pred_path = join(seq_path, 'predictions')
        for f in np.sort(os.listdir(pred_path)):
            test_result_file_list.append([join(pred_path, f)])
            break
    test_file_list = np.concatenate(test_result_file_list, axis=0)
    return test_file_list


if __name__ == '__main__':
    dataset_path = '/../../../../data/semantic_kitti/dataset/sequences' 
    predict_path = '/../../../../data/semantic_kitti/dataset/test/sequences'
    test_list = get_file_list(dataset_path)
    test_label_list = get_test_result_file_list(predict_path)
    BASE_DIR = dirname(abspath(__file__))

    #  remap_lut  #
    data_config = join(BASE_DIR, 'utils', 'semantic-kitti.yaml')
    DATA = yaml.safe_load(open(data_config, 'r'))
    remap_dict = DATA["learning_map"]
    max_key = max(remap_dict.keys())
    remap_lut = np.zeros((max_key + 100), dtype=np.int32)
    remap_lut[list(remap_dict.keys())] = list(remap_dict.values())
    #  remap_lut  #
    
    plot_colors = Plot.random_colors(21, seed=2)

    for i in range(len(test_list)):
        pc_path = test_list[i]
        labels_path = test_label_list[i]
        points = DP.load_pc_kitti(pc_path)

        # 用深蓝色画初始点云 #
        rpoints = np.zeros((points.shape[0],6),dtype=np.int)
        rpoints[:,0:3] = points
        rpoints[:,5] = 1
        Plot.draw_pc(rpoints)

        # 画对应的预测点云 #
        labels = DP.load_label_kitti(labels_path, remap_lut)
        Plot.draw_pc_sem_ins(points, labels,plot_colors)

三、Semantic3D绘图

绘制效果如下:

 

from helper_tool import Plot
from os.path import join, exists
from helper_ply import read_ply
import numpy as np
import os


if __name__ == '__main__':
    path = '/../../data'
    label_folder = './test/Log_2020-04-09_03-32-36/predictions/'

    label_to_names = {0: 'unlabeled',
                           1: 'man-made terrain',
                           2: 'natural terrain',
                           3: 'high vegetation',
                           4: 'low vegetation',
                           5: 'buildings',
                           6: 'hard scape',
                           7: 'scanning artefacts',
                           8: 'cars'}


    original_folder = join(path, 'semantic3d')
    full_pc_folder = join(path, 'original_ply')

    test_files_names = []
    cloud_names = [file_name[:-4] for file_name in os.listdir(original_folder) if file_name[-4:] == '.txt']
    for pc_name in cloud_names:
        if not exists(join(original_folder, pc_name + '.labels')):
            test_files_names.append(pc_name + '.ply')
    test_files_names = np.sort(test_files_names)
    # Ascii files dict for testing
    ascii_files = {
        'MarketplaceFeldkirch_Station4_rgb_intensity-reduced.ply': 'marketsquarefeldkirch4-reduced.labels',
        'sg27_station10_rgb_intensity-reduced.ply': 'sg27_10-reduced.labels',
        'sg28_Station2_rgb_intensity-reduced.ply': 'sg28_2-reduced.labels',
        'StGallenCathedral_station6_rgb_intensity-reduced.ply': 'stgallencathedral6-reduced.labels',
        'birdfountain_station1_xyz_intensity_rgb.ply': 'birdfountain1.labels',
        'castleblatten_station1_intensity_rgb.ply': 'castleblatten1.labels',
        'castleblatten_station5_xyz_intensity_rgb.ply': 'castleblatten5.labels',
        'marketplacefeldkirch_station1_intensity_rgb.ply': 'marketsquarefeldkirch1.labels',
        'marketplacefeldkirch_station4_intensity_rgb.ply': 'marketsquarefeldkirch4.labels',
        'marketplacefeldkirch_station7_intensity_rgb.ply': 'marketsquarefeldkirch7.labels',
        'sg27_station10_intensity_rgb.ply': 'sg27_10.labels',
        'sg27_station3_intensity_rgb.ply': 'sg27_3.labels',
        'sg27_station6_intensity_rgb.ply': 'sg27_6.labels',
        'sg27_station8_intensity_rgb.ply': 'sg27_8.labels',
        'sg28_station2_intensity_rgb.ply': 'sg28_2.labels',
        'sg28_station5_xyz_intensity_rgb.ply': 'sg28_5.labels',
        'stgallencathedral_station1_intensity_rgb.ply': 'stgallencathedral1.labels',
        'stgallencathedral_station3_intensity_rgb.ply': 'stgallencathedral3.labels',
        'stgallencathedral_station6_intensity_rgb.ply': 'stgallencathedral6.labels'}
    
    plot_colors = Plot.random_colors(11, seed=2)
    for file in test_files_names:
        print(file)
        test_files = join(full_pc_folder, file)
        label_files = join(label_folder, ascii_files[file])
        data = read_ply(test_files)
        # 绘制原图
        pc_xyzrgb = np.vstack((data['x'], data['y'], data['z'], data['red'], data['green'], data['blue'])).T
        Plot.draw_pc(pc_xyzrgb)
        # 绘制预测结果图
        pc_xyz = np.vstack((data['x'], data['y'], data['z'])).T
        pc_sem_ins = np.loadtxt(label_files)
        pc_sem_ins = pc_sem_ins.astype(int)
        Plot.draw_pc_sem_ins(pc_xyz, pc_sem_ins,plot_colors)

 

  • 11
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 57
    评论
### 回答1: randla-net是一种高效的大规模点云语义分割方法。它采用了一种新颖的点云降采样方法,可以在保持点云形状信息的同时大大减少点云数量。此外,它还使用了一种基于局部区域的特征提取方法,可以有效地捕捉点云中的局部特征。最终,randla-net可以在保持较高分割精度的同时,大大提高分割速度。 ### 回答2: Randla-Net是一种高效的大规模点云语义分割方法,它利用深度学习方法实现对三维点云数据中物体的自动识别和分类。在智能驾驶、金字塔建设、城市规划和3D建模等领域,点云数据已经成为一种重要的数据形式。在处理点云数据时,常常需要对点云中的各种物体进行语义分割,划分出物体的类别和边界,以进一步进行场景分析和建模。 Randla-Net的关键思想是将点云数据转换成局部规则网格(LHG)型式,然后对规则网格应用神经网络模型,实现对点云的语义分割。相较于传统的点云分割方法,Randla-Net的解决方案更加高效,并且能够适应大规模点云数据的处理。具体来说,Randla-Net采用的局部规则网格可以大大减少点云数据的复杂性,减少无效数据的计算,同时保证点云数据与原始数据的对应性。神经网络模型的引入能够提高计算的全局一致性,并在语义分割中对局部特征和位置被高效获取。此外,Randla-Net融合了RANDomized LAyered points(简称RANDLA)的思想,可以抽取多级别多方向的特征,使得点云数据在语义分割中的处理更加准确。 总之,Randla-Net是一种快速、有效、准确的大规模点云语义分割方法,其优点在于可以处理复杂的大规模点云数据,同时在语义分割中能够提供更高的计算效率和更精确的结果。它的应用将会推动点云技术的发展,为智能驾驶、建筑、机器人、VR/AR等领域提供更加精确的三维场景建模工具。 ### 回答3: RandLA-Net是一种高效而准确的点云语义分割神经网络,专为应对大规模点云场景而开发。该网络的核心功能在于通过快速地对点云数据进行聚类、降采样和投影等操作,实现了对点云进行语义分割,并能够输出详细的分割结果。 RandLA-Net相对于传统点云语义分割算法的优势在于,该算法不但能够处理大规模点云数据,同时还利用了矩阵分解的方法来提高运行速度。因此,该算法在极端情况下也能实现快速和准确的分割,如在不同分辨率、不同大小和不同密度的点云数据上。 RandLA-Net的另一个创新点在于使用了自适应滑动窗口的方法,就是通过分析点云的特征分布,来自动选择和匹配最适宜的窗口大小,以此进一步提高分割效果。同时,该算法还考虑到了实际应用场景中存在的地面、建筑物等不同的目标物体,对各自进行分割和处理,以期达到更高的准确率。 总的来说,RandLA-Net是一种高效、准确、可扩展的神经网络,为卫星、城市规划、无人驾驶等领域提供了强大的支持。该算法的研究提供了新的思路,为点云语义分割界的研究者提供了很好的启示,也为工业界解决实际问题提供了新的思路。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 57
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值