0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

点云处理——将激光雷达数据投影到二维图像

新机器视觉 来源:3D视觉开发者社区 2023-11-30 16:53 次阅读

“前视图”投影

为了将激光雷达传感器的“前视图”展平为2D图像,必须将3D空间中的点投影到可以展开的圆柱形表面上,以形成平面。

本文代码参考自论文《Vehicle Detection from 3D Lidar Using Fully Convolutional Network》

论文链接:https://arxiv.org/pdf/1608.07916.pdf

b2e63ca4-8f5b-11ee-939d-92fbcf53809c.png

b3210438-8f5b-11ee-939d-92fbcf53809c.png

# h_res = horizontal resolution of the lidar sensor
# v_res = vertical resolution of the lidar sensor
x_img = arctan2(y_lidar, x_lidar)/ h_res 
y_img=np.arctan2(z_lidar,np.sqrt(x_lidar**2+y_lidar**2))/v_res

问题在于这样做会将图像的接缝直接放在汽车的右侧。将接缝定位在汽车的最后部更有意义,因此前部和侧部更重要的区域是不间断的。让这些重要区域不间断将使卷积神经网络更容易识别那些重要区域中的整个对象。
以下代码解决了这个问题。

# h_res = horizontal resolution of the lidar sensor
# v_res = vertical resolution of the lidar sensor
x_img = np.arctan2(-y_lidar, x_lidar)/ h_res # seam in the back
y_img=np.arctan2(z_lidar,np.sqrt(x_lidar**2+y_lidar**2))/v_res

沿每个轴配置刻度

变量h r e s h_{res}和v r e s v_{res}非常依赖于所使用的LIDAR传感器。在KTTI数据集中,使用的传感器是Velodyne HDL 64E。根据Velodyne HDL 64E的规格表,它具有以下重要特征:

  • 垂直视野为26.9度,分辨率为0.4度,垂直视野被分为传感器上方+2度,传感器下方-24.9度

  • 360度的水平视野,分辨率为0.08-0.35(取决于旋转速度)

  • 旋转速率可以选择在5-20Hz之间

可以按以下方式更新代码:

# Resolution and Field of View of LIDAR sensor
h_res = 0.35         # horizontal resolution, assuming rate of 20Hz is used 
v_res = 0.4          # vertical res
v_fov = (-24.9, 2.0) # Field of view (-ve, +ve) along vertical axis
v_fov_total = -v_fov[0] + v_fov[1] 


# Convert to Radians
v_res_rad = v_res * (np.pi/180)
h_res_rad = h_res * (np.pi/180)


# Project into image coordinates
x_img = np.arctan2(-y_lidar, x_lidar)/ h_res_rad
y_img=np.arctan2(z_lidar,d_lidar)/v_res_rad

然而,这导致大约一半的点在x轴负方向上,并且大多数在y轴负方向上。为了投影到2D图像,需要将最小值设置为(0,0),所以需要做一些改变:

# SHIFT COORDINATES TO MAKE 0,0 THE MINIMUM
x_min = -360.0/h_res/2    # Theoretical min x value based on specs of sensor
x_img = x_img - x_min     # Shift
x_max = 360.0/h_res       # Theoretical max x value after shifting


y_min = v_fov[0]/v_res    # theoretical min y value based on specs of sensor
y_img = y_img - y_min     # Shift
y_max = v_fov_total/v_res # Theoretical max x value after shifting
y_max = y_max + 5         # UGLY: Fudge factor because the calculations based on
                          # spec sheet do not seem to match the range of angles
#collectedbysensorinthedata.

绘制二维图像

将3D点投影到2D坐标点,最小值为(0,0),可以将这些点数据绘制成2D图像。

pixel_values = -d_lidar # Use depth data to encode the value for each pixel
cmap = "jet"            # Color map to use
dpi = 100               # Image resolution
fig, ax = plt.subplots(figsize=(x_max/dpi, y_max/dpi), dpi=dpi)
ax.scatter(x_img,y_img, s=1, c=pixel_values, linewidths=0, alpha=1, cmap=cmap)
ax.set_axis_bgcolor((0, 0, 0)) # Set regions with no points to black
ax.axis('scaled')              # {equal, scaled}
ax.xaxis.set_visible(False)    # Do not draw axis tick marks
ax.yaxis.set_visible(False)    # Do not draw axis tick marks
plt.xlim([0, x_max])   # prevent drawing empty space outside of horizontal FOV
plt.ylim([0, y_max])   # prevent drawing empty space outside of vertical FOV
fig.savefig("/tmp/depth.png",dpi=dpi,bbox_inches='tight',pad_inches=0.0)

完整代码

把上面所有的代码放在一个函数中。

def lidar_to_2d_front_view(points,
                           v_res,
                           h_res,
                           v_fov,
                           val="depth",
                           cmap="jet",
                           saveto=None,
                           y_fudge=0.0
                           ):
    """ Takes points in 3D space from LIDAR data and projects them to a 2D
        "front view" image, and saves that image.


    Args:
        points: (np array)
            The numpy array containing the lidar points.
            The shape should be Nx4
            - Where N is the number of points, and
            - each point is specified by 4 values (x, y, z, reflectance)
        v_res: (float)
            vertical resolution of the lidar sensor used.
        h_res: (float)
            horizontal resolution of the lidar sensor used.
        v_fov: (tuple of two floats)
            (minimum_negative_angle, max_positive_angle)
        val: (str)
            What value to use to encode the points that get plotted.
            One of {"depth", "height", "reflectance"}
        cmap: (str)
            Color map to use to color code the `val` values.
            NOTE: Must be a value accepted by matplotlib's scatter function
            Examples: "jet", "gray"
        saveto: (str or None)
            If a string is provided, it saves the image as this filename.
            If None, then it just shows the image.
        y_fudge: (float)
            A hacky fudge factor to use if the theoretical calculations of
            vertical range do not match the actual data.


            For a Velodyne HDL 64E, set this value to 5.
    """


    # DUMMY PROOFING
    assert len(v_fov) ==2, "v_fov must be list/tuple of length 2"
    assert v_fov[0] <= 0, "first element in v_fov must be 0 or negative"
    assert val in {"depth", "height", "reflectance"}, 
        'val must be one of {"depth", "height", "reflectance"}'




    x_lidar = points[:, 0]
    y_lidar = points[:, 1]
    z_lidar = points[:, 2]
    r_lidar = points[:, 3] # Reflectance
    # Distance relative to origin when looked from top
    d_lidar = np.sqrt(x_lidar ** 2 + y_lidar ** 2)
    # Absolute distance relative to origin
    # d_lidar = np.sqrt(x_lidar ** 2 + y_lidar ** 2, z_lidar ** 2)


    v_fov_total = -v_fov[0] + v_fov[1]


    # Convert to Radians
    v_res_rad = v_res * (np.pi/180)
    h_res_rad = h_res * (np.pi/180)


    # PROJECT INTO IMAGE COORDINATES
    x_img = np.arctan2(-y_lidar, x_lidar)/ h_res_rad
    y_img = np.arctan2(z_lidar, d_lidar)/ v_res_rad


    # SHIFT COORDINATES TO MAKE 0,0 THE MINIMUM
    x_min = -360.0 / h_res / 2  # Theoretical min x value based on sensor specs
    x_img -= x_min              # Shift
    x_max = 360.0 / h_res       # Theoretical max x value after shifting


    y_min = v_fov[0] / v_res    # theoretical min y value based on sensor specs
    y_img -= y_min              # Shift
    y_max = v_fov_total / v_res # Theoretical max x value after shifting


    y_max += y_fudge            # Fudge factor if the calculations based on
                                # spec sheet do not match the range of
                                # angles collected by in the data.


    # WHAT DATA TO USE TO ENCODE THE VALUE FOR EACH PIXEL
    if val == "reflectance":
        pixel_values = r_lidar
    elif val == "height":
        pixel_values = z_lidar
    else:
        pixel_values = -d_lidar


    # PLOT THE IMAGE
    cmap = "jet"            # Color map to use
    dpi = 100               # Image resolution
    fig, ax = plt.subplots(figsize=(x_max/dpi, y_max/dpi), dpi=dpi)
    ax.scatter(x_img,y_img, s=1, c=pixel_values, linewidths=0, alpha=1, cmap=cmap)
    ax.set_axis_bgcolor((0, 0, 0)) # Set regions with no points to black
    ax.axis('scaled')              # {equal, scaled}
    ax.xaxis.set_visible(False)    # Do not draw axis tick marks
    ax.yaxis.set_visible(False)    # Do not draw axis tick marks
    plt.xlim([0, x_max])   # prevent drawing empty space outside of horizontal FOV
    plt.ylim([0, y_max])   # prevent drawing empty space outside of vertical FOV


    if saveto is not None:
        fig.savefig(saveto, dpi=dpi, bbox_inches='tight', pad_inches=0.0)
    else:
fig.show()

以下是一些用例:

import matplotlib.pyplot as plt
import numpy as np


HRES = 0.35         # horizontal resolution (assuming 20Hz setting)
VRES = 0.4          # vertical res
VFOV = (-24.9, 2.0) # Field of view (-ve, +ve) along vertical axis
Y_FUDGE = 5         # y fudge factor for velodyne HDL 64E


lidar_to_2d_front_view(lidar, v_res=VRES, h_res=HRES, v_fov=VFOV, val="depth",
                       saveto="/tmp/lidar_depth.png", y_fudge=Y_FUDGE)


lidar_to_2d_front_view(lidar, v_res=VRES, h_res=HRES, v_fov=VFOV, val="height",
                       saveto="/tmp/lidar_height.png", y_fudge=Y_FUDGE)


lidar_to_2d_front_view(lidar, v_res=VRES, h_res=HRES, v_fov=VFOV,
                       val="reflectance", saveto="/tmp/lidar_reflectance.png",
                       y_fudge=Y_FUDGE)

产生以下三个图像:

Depth

b337b46c-8f5b-11ee-939d-92fbcf53809c.png

Height

b34fcb10-8f5b-11ee-939d-92fbcf53809c.png

Reflectance

b373655c-8f5b-11ee-939d-92fbcf53809c.png

后续操作步骤

目前创建每个图像非常慢,可能是因为matplotlib,它不能很好地处理大量的散点。
因此需要创建一个使用numpy或PIL的实现。

测试

需要安装python-pcl,加载PCD文件。

sudo apt-get install python-pip


sudo apt-get install python-dev


sudo pip install Cython==0.25.2


sudo pip install numpy


sudo apt-get install git


git clone https://github.com/strawlab/python-pcl.git


cd python-pcl/


python setup.py build_ext -i


python setup.py install

可惜,sudo pip install Cython==0.25.2这步报错:

Cannot uninstall ‘Cython’. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.”

换个方法,安装pypcd:

pipinstallpypcd

查看 https://pypi.org/project/pypcd/ ,用例如下:

Example
-------


.. code:: python


import pypcd
# also can read from file handles.
pc = pypcd.PointCloud.from_path('foo.pcd')
# pc.pc_data has the data as a structured array
# pc.fields, pc.count, etc have the metadata


# center the x field
pc.pc_data['x'] -= pc.pc_data['x'].mean()


# save as binary compressed
pc.save_pcd('bar.pcd', compression='binary_compressed')

测试数据结构:

“ >>> lidar = pypcd.PointCloud.from_path(‘~/pointcloud-processing/000000.pcd’)

>>> lidar.pc_data

array([(18.323999404907227, 0.04899999871850014, 0.8289999961853027, 0.0),

(18.3439998626709, 0.10599999874830246, 0.8289999961853027, 0.0),

(51.29899978637695, 0.5049999952316284, 1.944000005722046, 0.0),

…,

(3.7139999866485596, -1.3910000324249268, -1.7330000400543213, 0.4099999964237213),

(3.9670000076293945, -1.4739999771118164, -1.8569999933242798, 0.0),

(0.0, 0.0, 0.0, 0.0)],

dtype=[(‘x’, ‘

>>> lidar.pc_data[‘x’]

array([ 18.3239994 , 18.34399986, 51.29899979, …, 3.71399999,

3.96700001, 0. ], dtype=float32) ”

加载PCD:

import pypcd


lidar=pypcd.PointCloud.from_path('000000.pcd')

x_lidar:

x_lidar=points[’x‘]

结果:

Depth

b38c146c-8f5b-11ee-939d-92fbcf53809c.png

Height

b39e1914-8f5b-11ee-939d-92fbcf53809c.png

Reflectance

b3b3e32a-8f5b-11ee-939d-92fbcf53809c.png


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 传感器
    +关注

    关注

    2553

    文章

    51511

    浏览量

    757255
  • 变量
    +关注

    关注

    0

    文章

    613

    浏览量

    28501
  • 激光雷达
    +关注

    关注

    969

    文章

    4041

    浏览量

    190544

原文标题:点云处理——将激光雷达数据投影到二维图像

文章出处:【微信号:vision263com,微信公众号:新机器视觉】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    激光雷达是自动驾驶不可或缺的传感器

    看到这种低成本的激光雷达,从研发、样品商用,可能会比原来预想的周期更快。因为不是一家激光雷达公司在努力,而是整个产业链都在努力。是在同
    发表于 09-08 17:24

    激光雷达分类以及应用

    激光雷达实际上是一种工作在光学波段(特殊波段)的雷达,它的优点非常明显:1、具有极高的分辨率:激光雷达工作于光学波段,频率比微波高2~3个数量级以上,因此,与微波雷达相比,
    发表于 09-19 15:51

    激光雷达面临的机遇与挑战

    机遇激光雷达在智能机器生态系统中有很多机遇。与使用二维图像相比,能够更容易的被计算机使用,用于构建物理环境的三
    发表于 09-26 14:30

    北醒固态设计激光雷达

    其他展位,两台固态雷达数据实现完美的融合,特别彰显了北醒已经解决了困扰flash Lidar已久的互相干扰的技术难题,更好地服务于大
    发表于 01-25 09:36

    固态设计激光雷达

    其他展位,两台固态雷达数据实现完美的融合,特别彰显了北醒已经解决了困扰flash Lidar已久的互相干扰的技术难题,更好地服务于大
    发表于 01-25 09:41

    激光雷达除了可以激光测距外,还可以怎么应用?

    简单的3D雷达,获取三数据呢?目前市面上主流的有2种方式:1、采用线状激光器,原先的一个
    发表于 05-11 15:33

    激光雷达知多少:从技术上讲讲未来前景

    地区三控制和数字地面模型的获取提供了新的途径,无论对于国防或是科学研究都具有十分重大意义。星载激光雷达还具有观察整个天体的能力,美国进行的月球和火星等探测计划中都包含了星载激光雷达
    发表于 07-14 07:56

    一种不依赖于棋盘格等辅助标定物体实现像素级相机和激光雷达自动标定的方法

    变换方式区分性能不好,提供的约束效果不好:进一步指出投影图像平面再提取特征的问题主要在于
    发表于 09-01 07:42

    如何设计一款适合于果园应用的激光雷达

    1、概述由于课题要求,需要设计一款适合于果园应用的激光雷达。因此采用单线扫描激光雷达和角度传感器来设计能采集二维数据激光雷达。关于
    发表于 11-12 08:15

    激光雷达数据分割算法的嵌入式平台上的部署实现

    点击上方“AI算法修炼营”,选择“星标”公众号精选作品,第一时间送达这篇文章是激光雷达数据分割算法的嵌入式平台上的部署实现。主要的创新
    发表于 12-21 08:28

    激光雷达数据

    原来,这些都是激光雷达(LiDAR)数据,每一个都包含了三坐标信息,也是我们常说的X、Y
    的头像 发表于 09-24 12:29 1.3w次阅读
    <b class='flag-5'>激光雷达</b><b class='flag-5'>点</b><b class='flag-5'>云</b><b class='flag-5'>数据</b>

    关于激光雷达传感器如何投影二维图像

    为了激光雷达传感器的“前视图”展平为2D图像,必须将3D空间中的投影可以展开的圆柱形表面上
    的头像 发表于 04-03 09:58 2536次阅读
    关于<b class='flag-5'>激光雷达</b>传感器如何<b class='flag-5'>投影</b>成<b class='flag-5'>二维</b><b class='flag-5'>图像</b>

    详解激光雷达数据处理过程

    随着激光雷达的上车数量的不断攀升,如何用好激光雷达成为了重中之重,而用好激光雷达的关键之一就在于处理好点
    的头像 发表于 03-14 09:36 4112次阅读

    瑞识科技推出用于激光雷达二维可寻址VCSEL芯片并获量产订单

    随着汽车智能化和自动驾驶技术的快速发展,车载激光雷达市场近年呈现出高速增长的态势。近日,瑞识科技推出新款二维可寻址激光雷达VCSEL芯片,可应用于搭载固态激光雷达的智驾方案,以实现更高
    的头像 发表于 04-01 11:16 1023次阅读
    瑞识科技推出用于<b class='flag-5'>激光雷达</b>的<b class='flag-5'>二维</b>可寻址VCSEL芯片并获量产订单

    激光雷达数据包含哪些信息

    )、环境监测、城市规划等领域。激光雷达数据激光雷达系统收集的一系列三
    的头像 发表于 08-29 17:18 1129次阅读