处理点云数据(一):点云与生成鸟瞰图

2023-11-10

点云数据

点云数据一般表示为N行,至少三列的numpy数组。每行对应一个单独的点,所以使用至少3个值的空间位置点(X, Y, Z)来表示。
1
如果点云数据来自于激光雷达传感器,那么它可能有每个点的附加值,在KITTI数据中就有一个“反射率”,这是衡量激光光束在那个位置被反射回来了多少。所以在KITTI数据中,其点云数据就是N*4的矩阵。

图像与点云坐标

图像的坐标轴和点云的坐标轴是不同的,下图显示了蓝色的图像轴和橙色的点云轴。
2
关于图像坐标轴:
1、图像中的坐标值总是正的。
2、原点位于左上角。
3、坐标是整数值。

关于点云坐标轴:
1、点云的坐标值可以是正数也可以是负数。
2、坐标是实数。
3、正X轴代表前方。
4、正Y轴代表左边。
5、正Z轴代表上方。

创建点云数据中的鸟瞰图

鸟瞰图的相关坐标轴

3
如上图,鸟瞰图中的点云的相关轴为X和Y轴。同时,要考虑以下几点:
1、X和Y轴意味着是相反的
2、X和Y轴指向相反方向的
3、将点云的数值转换到图像上,使得(0, 0)是图像中最小的值。

限制矩形区域

将注意力集中于点云的特殊区域通常是有用的,对此,需要创建一个过滤器,保留感兴趣区域内的点。

矩形区域设置为距离原点两侧10米,前方20米。

side_range=(-10, 10) # 最左到最右
fwd_range=(0, 20) # 最后到最前

创建一个过滤器,只保留位于我们指定的矩形内的点

# 提取每个轴的点数
x_points = points[:, 0]
y_points = points[:, 1]
z_points = points[:, 2]

# 过滤器 - 仅返回立方体内点的索引
# 三个过滤器用于前后,左右,高度范围
# 雷达坐标系中左侧是正Y轴
f_filt = np.logical_and((x_points > fwd_range[0]), (x_points < fwd_range[1]))
s_filt = np.logical_and((y_points > -side_range[1]), (y_points < -side_range[0]))
filter = np.logical_and(f_filt, s_filt)
indices = np.argwhere(filter).flatten()

# 保留的点
x_points = x_points[indices]
y_points = y_points[indices]
z_points = z_points[indices]

映射点位置到像素位置

在点云数据中,其数据为实数,而映射到的图像数据为整数,若只是单纯的取整,将会丢失很多分辨率。

如果计量单位是米,想要一个5厘米的分辨率,则:

res = 0.05  # 转换为像素位置的值 - 基于分辨率
x_img = (-y_points / res).astype(np.int32)  # X轴在点云坐标系-Y上
y_img = (-x_points / res).astype(np.int32)  # Y轴在点云坐标系-X上

转换新的坐标原点

因为x, y 仍然有负值,所以需要移动数据使得(0, 0)为最小值。

x_img -= int(np.floor(side_range[0] / res))
y_img += int(np.ceil(fwd_range[1] / res))

像素值

将点云数据(Z轴,代表高度)填充到图像像素上去。设置一个想要关注的高度值范围,高于或低于该范围内的值都会被剪切到最大值和最小值,这能从感兴趣区域获得大量的细节。

根据点的高度填充到图像上,调整在0-255之间。

height_range = (-2, 0.5)  # 最低到最高

# 剪切高度值 
pixel_values = np.clip(a = z_points,
                       a_min=height_range[0],
                       a_max=height_range[1])

将值调整在0-255

def scale_to_255(a, min, max, dtype=np.uint8):
    """ 将指定的最小值,最大值范围的值数组缩放到0-255
        可以指定输出的数据类型(默认是uint8)
    """
    return (((a - min) / float(max - min)) * 255).astype(dtype)

# 调整高度值
pixel_values  = scale_to_255(pixel_values, min=height_range[0], max=height_range[1])

创建图像数组

# INITIALIZE EMPTY ARRAY - of the dimensions we want
x_max = 1+int((side_range[1] - side_range[0])/res)
y_max = 1+int((fwd_range[1] - fwd_range[0])/res)
im = np.zeros([y_max, x_max], dtype=np.uint8)

# FILL PIXEL VALUES IN IMAGE ARRAY
im[y_img, x_img] = pixel_values

可视化

from PIL import Image
im2 = Image.fromarray(im)
im2.show()

光谱色彩映射

import matplotlib.pyplot as plt
plt.imshow(im, cmap="spectral", vmin=0, vmax=255)
plt.show()

鸟瞰图生成完整代码

import numpy as np


# ==============================================================================
#                                                                   SCALE_TO_255
# ==============================================================================
def scale_to_255(a, min, max, dtype=np.uint8):
    """ Scales an array of values from specified min, max range to 0-255
        Optionally specify the data type of the output (default is uint8)
    """
    return (((a - min) / float(max - min)) * 255).astype(dtype)


# ==============================================================================
#                                                         POINT_CLOUD_2_BIRDSEYE
# ==============================================================================
def point_cloud_2_birdseye(points,
                           res=0.1,
                           side_range=(-10., 10.),  # left-most to right-most
                           fwd_range = (-10., 10.), # back-most to forward-most
                           height_range=(-2., 2.),  # bottom-most to upper-most
                           ):
    """ Creates an 2D birds eye view representation of the point cloud data.

    Args:
        points:     (numpy array)
                    N rows of points data
                    Each point should be specified by at least 3 elements x,y,z
        res:        (float)
                    Desired resolution in metres to use. Each output pixel will
                    represent an square region res x res in size.
        side_range: (tuple of two floats)
                    (-left, right) in metres
                    left and right limits of rectangle to look at.
        fwd_range:  (tuple of two floats)
                    (-behind, front) in metres
                    back and front limits of rectangle to look at.
        height_range: (tuple of two floats)
                    (min, max) heights (in metres) relative to the origin.
                    All height values will be clipped to this min and max value,
                    such that anything below min will be truncated to min, and
                    the same for values above max.
    Returns:
        2D numpy array representing an image of the birds eye view.
    """
    # EXTRACT THE POINTS FOR EACH AXIS
    x_points = points[:, 0]
    y_points = points[:, 1]
    z_points = points[:, 2]

    # FILTER - To return only indices of points within desired cube
    # Three filters for: Front-to-back, side-to-side, and height ranges
    # Note left side is positive y axis in LIDAR coordinates
    f_filt = np.logical_and((x_points > fwd_range[0]), (x_points < fwd_range[1]))
    s_filt = np.logical_and((y_points > -side_range[1]), (y_points < -side_range[0]))
    filter = np.logical_and(f_filt, s_filt)
    indices = np.argwhere(filter).flatten()

    # KEEPERS
    x_points = x_points[indices]
    y_points = y_points[indices]
    z_points = z_points[indices]

    # CONVERT TO PIXEL POSITION VALUES - Based on resolution
    x_img = (-y_points / res).astype(np.int32)  # x axis is -y in LIDAR
    y_img = (-x_points / res).astype(np.int32)  # y axis is -x in LIDAR

    # SHIFT PIXELS TO HAVE MINIMUM BE (0,0)
    # floor & ceil used to prevent anything being rounded to below 0 after shift
    x_img -= int(np.floor(side_range[0] / res))
    y_img += int(np.ceil(fwd_range[1] / res))

    # CLIP HEIGHT VALUES - to between min and max heights
    pixel_values = np.clip(a=z_points,
                           a_min=height_range[0],
                           a_max=height_range[1])

    # RESCALE THE HEIGHT VALUES - to be between the range 0-255
    pixel_values = scale_to_255(pixel_values,
                                min=height_range[0],
                                max=height_range[1])

    # INITIALIZE EMPTY ARRAY - of the dimensions we want
    x_max = 1 + int((side_range[1] - side_range[0]) / res)
    y_max = 1 + int((fwd_range[1] - fwd_range[0]) / res)
    im = np.zeros([y_max, x_max], dtype=np.uint8)

    # FILL PIXEL VALUES IN IMAGE ARRAY
    im[y_img, x_img] = pixel_values

    return im

特别说明:本文为本人学习所做笔记。
具体参考:http://ronny.rest/tutorials/module/pointclouds_01/point_cloud_birdseye/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

处理点云数据(一):点云与生成鸟瞰图 的相关文章

  • KITTI Visual Odometry 榜单(视觉SLAM排行)

    排名榜单最靠前 xff0c 看来说比T265好也不为过啊 果然好像靠这种榜单体现出来 xff0c 当初深度学习imagenet不也是在比赛中一军突起 xff0c 所以你完全可以去参加这些比赛 xff0c 结果说话 xff0c 不分学校和什么
  • ORB_SLAM2运行KITTI数据集

    在前文我们已经安装运行了ORB SLAM2 xff0c 下载和编译 xff08 包括报错 xff09 在文章 xff1a ORB SLAM2下载编译及运行EuRoC数据集 浅梦语11的博客 CSDN博客 euroc数据集下载 并且我们使用运
  • KITTI数据集简介与使用

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 摘要 xff1a 本文融合了Are we ready for Autonomous Driving The KITTI Vision
  • 将kitti数据集中的velodyne points转换为ROS bag文件

    kitti数据集中包含了相机图像 激光扫描得到的点云信息 高精度GPS测量信息和IMU加速度信息 xff0c 用于移动机器人与自动驾驶方面的研究 如下为数据采集平台示意图 kitti数据集中的激光扫描数据是以二进制文件形式存储的 xff0c
  • Vins-fusion用到的kitti数据集轨迹对不齐,使用evo -a转换

    kitti数据集基准问题 下面两个图一个是转换前 xff0c 一个是evo a 转换后的 问题描述 xff1a 现在遇到的问题是groundtruth和估计的位姿没有在一个坐标系中 xff0c 生成的轨迹对不齐 xff0c 需要首先根据位姿
  • KITTI数据集国内下载地址

    文件列表 xff1a http www functionweb tk kitti 如果遭遇下载失败的情况请访问 https blog csdn net weixin 43599336 article details 87801040 原始图
  • 基于KITTI数据集的KERAS-YOLOV3实践

    数据整理 KERAS YOLOV3的GITHUB地址 xff1a https github com yangchengtest keras yolo3 该项目支持的数据结构 xff1a One row for one image Row f
  • 点云基本概念

    文章目录 一 三维数据的表现形式 二 点云的概念 三 点云的特点 四 点云的获取方式 激光雷达 结构光 立体视觉 TOF相机 一 三维数据的表现形式 三维数据的表现形式一般分为四种 分别是点云 网格 体素与多视图 点云是三维空间中点的集合
  • 基于三维激光点云的树木建模(枝叶分离)

    基于三维激光点云的树木建模 2019 05 30 三维激光点云数据采集 2019 06 15 点云的枝叶分离 树枝 树干提取 枝干骨架提取 枝干骨架优化 构建三维模型 测试软件 链接 https pan baidu com s 1LhxOg
  • 点云高度归一化处理(附 python 代码)

    gt 由于不同地物之间存在着高程的差异 为了去除地形起伏对点云数据高程值的影响 所以需要根据提取出的地面点进行点云归一化处理 这一步是很多算法的基础 可以提高后续点云分类或分割的准确度等 如下图所示 gt 归一化的过程其实相对简单 遍历每一
  • mesh 模拟加入噪音数据,并根据每个三角形集群的数量进行去噪处理(附open3d python 代码)

    本篇文章对三角网格模型进行分割和去噪处理 其中包括以下主要步骤 1 使用Open3D库中的 o3d io read triangle mesh 函数读取PLY格式的三角网格模型 2 生成小立方体作为噪声 并将其添加到原始的三角网格模型中 3
  • 彩色点云显示方法(ArcScene)

    使用ArcScene显示彩色点云 撰写论文时想添加几张点云图片 但是利用cloudcompare显示的点云图像看起来实在是low 故曲线救国 探索了一种看起来稍微不那么low的显示方法 先对点云赋色 然后利用ArcScene显示 为避免自己
  • Point-GNN README批注

    Point GNN README批注 Point GNN 1 Getting Started 1 1 Prerequisites 1 2 KITTI Dataset 1 3 Download Point GNN 2 Inference 2
  • 百度Apollo(二):障碍物感知模块

    Apollo感知模块具有识别障碍物和交通灯的能力 其中 Apollo解决的障碍物感知问题 1 高精地图ROI过滤器 HDMap ROI Filter 2 基于卷积神经网络分割 CNN Segmentation 3 MinBox 障碍物边框构
  • 粗略的计算PCD点云的体积和表面积(非精确计算,python代码)

    读取的点云数据进行凸包计算 使用PointCloud对象的compute convex hull方法 返回凸包模型和凸包模型中点的索引 给凸包模型渲染颜色 使用TriangleMesh对象的paint uniform color方法 计算凸
  • c++ 代码连接激光雷达,使用 pybind11 得到python模块,可以直接在python中连接雷达,获取 numpy 格式激光数据

    注意 这个程序最后需要编译为 python 的一个模块 然后导入python中使用 底层原理是python调用c 程序连接激光雷达 然后把获取的数据转换为numpy格式 因为用python太慢了 C 函数 用于获取一个帧的数据并将其转换为P
  • 基于点云的3D障碍物检测

    基于点云的3D障碍物检测 主要有以下步骤 点云数据的处理 基于点云的障碍物分割 障碍物边框构建 点云到图像平面的投影 点云数据的处理 KITTI数据集 KITTI数据集有四个相机 主要使用第三个相机 序号为02 拍摄的图片 标定参数和标签文
  • 【KITTI】KITTI数据集简介(一) — 激光雷达数据

    本文为博主原创文章 未经博主允许不得转载 本文为专栏 python三维点云从基础到深度学习 系列文章 地址为 https blog csdn net suiyingy article details 124017716 KITTI数据集的详
  • 点云 pillar 形状的数据搜索

    读取点云数据 将点云数据中的某一个维度设置为0 生成一个新的点云数据 并建立其上的KDTree索引 给定查询点并对查询点进行半径搜索 并将半径邻域内的点渲染为红色 最后得到就是该点范围内 一个圆柱形的附近点集合 最后将可视化结果展示出来 代
  • 单目相机测距(3米范围内)二维码实现方案(python代码 仅仅依赖opencv)

    总体思路 先通过opencv 识别二维码的的四个像素角位置 然后把二维码的物理位置设置为 cv Point3f HALF LENGTH HALF LENGTH 0 tl cv Point3f HALF LENGTH HALF LENGTH

随机推荐

  • angular6之pipe管道

    作为前端开发人员 我们在网站开发时 需要读取后端的接口进行视图层的数据展示 我们经常会遇到接口给予我们的值不是最终展现的数据 例如 后端返回的金额是number类型额数据 我们需要遇到千分位用逗号隔开 10000 gt 10 000 重量1
  • debian系统安装软件方法

    基于Debian的linux系统软件安装命令
  • 程序环境和预处理详解

    你好 我是史丰源 欢迎你的来访 希望我的博客能给你带来一些帮助 我的Gitee 代码仓库 我的联系方式 QQ 1756786195 邮箱 Marksky126 outlook com 程序环境和预处理 一 程序的翻译环境和执行环境 二 详解
  • Linux中gcc的常用命令

    目录 一 简介 二 简单编译 1 预处理 2 编译 3 汇编 4 连接 5 执行 三 多个程序文件的编译 四 检错 五 库文件连接 1 编译成可执行文件 2 链接 3 强制链接时使用静态链接库 六 小结 七 参考文献 一 简介 GCC 是编
  • Ubuntu安装Python3

    Python2中文的解决 在py文件第一行添加 coding utf 8 规范的应该这么写 coding utf 8 安装python 系统默认安装Python2 安装Python3的命令 sudo apt get install pyth
  • Python实现爬虫的简单示例

    Python实现爬虫 一 介绍 网络爬虫是一种自动获取互联网信息的程序 可以用于抓取各种网站上的数据 本文将介绍如何使用Python编写一个简单的爬虫 来抓取文章 二 环境准备 在开始编写爬虫之前 需要安装Python和相关的第三方库 请确
  • 【Java】猜数字游戏(面向对象 封装成类)

    一 猜数字游戏类 menu 公开 方法 参数 无 返回值 无 主要是显示菜单 并决定是否进入游戏 guessNumber 私有 方法 参数1 生成的随机幸运数 0 100 参数2 Scanner对象 应为主方法中已生成过了 所以直接传进来用
  • Python+获取外网IP+并发送指定邮件 (一)

    需求 如果我们家里或者公司有nas服务器 或者其他需要外网访问的设备及应用 我们应怎么做 1 拉专线 运营商会给你公网ip 除大公司或企业以外不推荐 优点 网速快 带宽高 且ip固定 缺点 烧钱 2 使用软件做域名解析 如 某生壳 某桌互联
  • Kubernetes 的证书认证

    今天让我们聊聊 Kubernetes 的公私钥和证书认证 本文内容会提及如何根据需要对 CA 公私钥进行组织并对集群进行设置 Kubernetes 的组件中有很多不同的地方可以放置证书之类的东西 在进行集群安装的时候 我感觉有一百多亿个不同
  • JavaScript 闭包

    目录 全局变量 实例 实例 变量的生命周期 一个计数器的困境 实例 实例 实例 JavaScript 嵌套函数 实例 JavaScript 闭包 实例 例子解释 闭包的概念 闭包的特点 使用闭包的注意点 参考资料 JavaScript 变量
  • 文件IO(二.标准IO)

    标准IO 1 为什么需要标准IO 每个操作系统下面 对文件的管理和接口是不一样 linux open read write window winopen 同一个文件 在不同的操作系统下面 操作文件的代码是不一样 此时 代码就比较难写 我们在
  • 添加halcon图像显示控件_C#与Halcon联合编程步骤

    1 编程环境 Windows10 64位 VS2013 Halcon12 64位 2 第一步 配置环境变量 path C ProgramFilesMVTecHALCON 12 0bindotnet35 和 C Program FilesMV
  • 用这个工具,发朋友圈都可以自动了

    今天推荐是一个比较骚气的工具 自动发朋友圈 不用root手机 对于一天发10多条 甚至20条朋友圈的朋友 每次编辑比较麻烦 我之前也写过抢红包工具 当时上架应用市场时 又恰逢过年 那下载量 比我吃了一桶老坛酸菜面还爽 后来由于应用市场的限制
  • 14-QDockWidget

    QDockWidget QDockWidget border 1px solid red titlebar close icon url images 111 bmp titlebar normal icon url images clos
  • 2023!6招玩转 Appium 自动化测试

    Appium是个什么鬼 Appium是一个移动端的自动化框架 可用于测试原生应用 移动网页应用和混合型应用 且是跨平台的 可用于IOS和Android以及firefox的操作系统 原生的应用是指用android或ios的sdk编写的应用 移
  • 安装博图时出现缺少.net3.5sp1解决办法

    第一步 打开控制面板 点击程序 第二步 点击启用或关闭Windows功能 第三步 勾选如图所示的三个选择框 点击确定 第四步 点击让Windows更新为你下载文件 第五步 等待安装完成 安装过程失败出现错误的解决办法 作者安装失败的原因是因
  • ACmix 自注意力和卷积集成 On the Integration of Self-Attention and Convolution+

    自注意力和卷积 自注意力 1 1 卷
  • 去除 

    python 的strip 可以去除特殊空格 关于特殊空格 nbsp可以参考 http love67 net 2017 04 07 trim nbsp nbsp的unicode编码是160 正常的空格Unicode编码是32 gt gt g
  • Tomcat 弱密码爆破 漏洞复现

    Tomcat 弱密码爆破 漏洞复现 一 漏洞描述 二 漏洞影响 三 漏洞复现 1 环境搭建 2 漏洞复现 四 漏洞POC 五 参考链接 一 漏洞描述 Tomcat有一个管理后台 其用户名和密码在Tomcat安装目录下的conf tomcat
  • 处理点云数据(一):点云与生成鸟瞰图

    点云数据 点云数据一般表示为N行 至少三列的numpy数组 每行对应一个单独的点 所以使用至少3个值的空间位置点 X Y Z 来表示 如果点云数据来自于激光雷达传感器 那么它可能有每个点的附加值 在KITTI数据中就有一个 反射率 这是衡量