第二章 python-pcl、open3d读取、显示pcd、bin格式点云数据

文章目录

    • 第二章 python-pcl、open3d读取、显示pcd、bin格式点云数据
  • 前言
  • 环境
  • 一、点云数据类型
    • 1.基于python-pcl 读取显示pcd、bin格式文件
    • 2.基于open3d 读取显示pcd格式文件
    • 3.解析pcap格式点云文件并通过python-pcl显示
  • 总结

前言

点云数据实际上就是许多组点的集合,每个点由{x,y,z}组成。当然理论上的只包含有3D坐标。
实际激光雷达获取的点云数据还会包含强度、反射率等等。但我们一般只用提取{x,y,z}来处理即可。

点云数据相比于其他传感器数据的核心优势就是在于 精准的深度信息。可惜获取具体的坐标信息。

环境

因为涉及到深度学习的应用,所以运用的整体环境是基于 python 使用pycharm编辑。
主要涉及库 python-pcl open3D mayavi numpy 等等用来处理点云数据并显示。

实际上点云的核心处理库应该是PCL 类似于图像处理中的Opencv 。后面也会有扩展。

一、点云数据类型

基于激光雷达录制的点云文件具有多种格式,如pcd、npy、ply、bin、pcap、lvx等等。
而读取点云数据也有多个库,python-pcl open3D mayavi numpy。
这里主要使用 python-pcl 和 open3D 两个核心库。

1.基于python-pcl 读取显示pcd、bin格式文件

代码如下(示例):

import numpy as np
import pcl.pcl_visualization
pt = pcl.load("D://code-python//Data//lidar//2094.799809520.pcd")#转为数组 形如 24000 x 3
points = pt.to_array()#但是pcl显示是要 N*4 所以要扩展一列 取一列插入数组使 N*3 变为 N*4
x = points[:,0]
points = np.insert(points,3,x,axis=1)# 这里对第四列进行赋值,它代表颜色值,根据你自己的需要赋值即可;
points[:, 3] = 255# PointCloud_PointXYZRGB 需要点云数据是N*4,分别表示x,y,z,RGB ,其中RGB 用一个整数表示颜色;
color_cloud = pcl.PointCloud_PointXYZRGB(points)
visual = pcl.pcl_visualization.CloudViewing()#窗口名
visual.ShowColorCloud(color_cloud, b'sta')flag = True
while flag:flag != visual.WasStopped()

这里就可以成功显示 颜色是根据自己设置

下面基于 numpy 读取bin格式点云文件

import pcl.pcl_visualization
import numpy as np# lidar_path 指定一个kitti 数据的点云bin文件就行了
#bin文件为2进制文件
lidar_path = r'D:/code-python/Data/lidar/000000.bin'# reshape成 N*4
points = np.fromfile(lidar_path, dtype=np.float32).reshape(-1, 4)  # 在这里对第四列进行赋值,它代表颜色值,根据你自己的需要赋值即可;
points[:,3] = 255# PointCloud_PointXYZRGB 需要点云数据是N*4,分别表示x,y,z,RGB ,其中RGB 用一个整数表示颜色;
color_cloud = pcl.PointCloud_PointXYZRGB(points)
visual = pcl.pcl_visualization.CloudViewing()
visual.ShowColorCloud(color_cloud, b'cloud')
flag = True
while flag:flag != visual.WasStopped()

2.基于open3d 读取显示pcd格式文件

代码如下(示例):

import open3d as o3d
import numpy as nppoint = o3d.io.read_point_cloud("D:/code-python/Data/lidar/000000.pcd")o3d.visualization.draw_geometries([point])#open3d显示的时候有个bug 要把python  pycharm设置为高性能  系统显示里 图形设置


效果相对于 python-pcl的显示还是差一点,不过也挺不错。同时是可以调的,它也是一个成熟的3D处理库。有许多内置的处理函数。

3.解析pcap格式点云文件并通过python-pcl显示

这里参考一位大佬的代码:
作者:lonlon ago
https://zhuanlan.zhihu.com/p/158621756
代码如下:


# -*- coding: UTF-8 -*-
import dpkt
import collections  # 有序字典需要的模块
import time
import numpy as np
import struct# 安装了pcl , 可以使用它来进行可视化
import pcl.pcl_visualization
viewer = pcl.pcl_visualization.PCLVisualizering()#初始化一个对象
viewer.SetBackgroundColor(0, 0, 0) #颜色
viewer.AddCoordinateSystem()
viewer.InitCameraParameters()# vlp 16 的参数
'''
https://blog.csdn.net/qq_34911636/article/details/89946329#commentBox
激光雷达每一帧的数据长度固定为1248字节,其中分别为前42字节的前数据包标识、12组数据包、4字节时间戳和最后两字节雷达型号参数。
12组数据包中前两字节为数据包的开始标识(0xFFEE)、接下去两字节为的旋转角度(当前角度)值和连续32*(2字节的距离值+1字节的激光反射强度值)字节的距离信息,
其中32*3字节分别为雷达两次获取探测信息,每个数据包开头所携带的旋转角度是指当前数据包前16*3字节对应的角度,而后16*3字节对应的旋转角度激光雷达没有直接给出,
需要通过计算前后两次旋转角度然后求取平均值获得。
1248 = 42 + 12*(2 + 2 + 32*(2+1)) + 4 + 2 =1248雷达扫描频率为10Hz,每秒数据包在480帧左右,即每次扫描会产生48个左右的数据包,需要将分散的数据包数据合并称为一次扫描的点云数据
75个udp包产生一圈数据 vlp格式解析那篇文章 下面评论没理解 为什么是75 75*384*10 = 288000
若按照这样理解 角分辨率按照0.1度 360/0.1 = 3600 一圈转3600次 一次16个点 = 57600 10hz 1s 10圈 即 57600*10 = 576000 反正
有点乱
'''
DISTANCE_RESOLUTION = 0.002   # 距离数值分辨率 2mm转换为单位米
udp_package_num = 1
line_per_udp = 12        # 每个UDP 有多少列
point_per_udp_line = 32  # 每个UDP 的每列包含有多少个点
point_num_per_udp = point_per_udp_line * line_per_udp  # 32*12=384thetas_lines = [-15, 1, -13, 3, -11, 5, -9, 7, -7, 9, -5, 11, -3, 13, -1, 15] #垂直角度w代表值
thetas_point = thetas_lines * 2 * line_per_udp * udp_package_num   #感觉是嵌套列表 列表乘以一个数字 [[x],[x],[x]...]
thetas_point = np.radians(thetas_point) #角度从度转为弧度 thetas_point为输入的角度 它返回一个数组, 其中包含输入数组中给定度数的等效弧度角。
thetas_point_cos = np.cos(thetas_point)  #cos弧度
thetas_point_sin = np.sin(thetas_point)  #sin弧度data_fmt = '<' + (('H' + 'H' + 'HB' * point_per_udp_line) * line_per_udp + 'IH') * udp_package_num
base_range = np.array(range(2, point_per_udp_line*2+1, 2))  # 32, 距离值的基础索引
#range (start,stop,step) range(2,65,2) 32个数
angle_base_range = np.array([1])
d_range = []
r_range = []
angle_range = []
k = 0
data_gap = 2 + 2*point_per_udp_line  # 每一列的长度 其实是2字节标识 2字节旋转角度 32*(2字节距离,1字节反射强度)点 这里貌似只计算旋转角度+距离66for i in range(udp_package_num):for j in range(line_per_udp):d_range.append(base_range + k * data_gap + i * 2)  # 66 是 HH + HB*32  d.range 列表增加,多个列表嵌套r_range.append(base_range + k * data_gap + i * 2 + 1)angle_range.append(angle_base_range + k * data_gap + i * 2)k += 1
d_range = np.hstack(d_range)  # 多个array组成的列表
r_range = np.hstack(r_range)
angle_range = np.hstack(angle_range)# 水平角度插值,如果有角度跳变会怎么样?  针对从360跳变到20的这部分拟合的并不是很好,误差很大;已经改正
x_index = np.arange(point_num_per_udp)
xp_index = np.arange(0, point_num_per_udp, point_per_udp_line) # array([  0,  32,  64,  96, 128, 160, 192, 224, 256, 288, 320, 352])def unpack_udp(data):data_tuple = struct.unpack(data_fmt, data)  # 原始格式是元祖,要转array,元祖不能索引data_unpack = np.array(data_tuple, dtype=np.int64)  # np.array会多耗时15毫秒  todo 这里为什么会报错?? 可能是时间戳的数值太大了distances = data_unpack[d_range]  # 115200refs = data_unpack[r_range] / 255angles = data_unpack[angle_range]angles = np.radians(angles / 100).astype(np.float32)  # 除以100再弧度值# 第一种处理角度的方式# angles = np.tile(angles, (32, 1)).flatten('F')  # 因为angle只有1个,数据有32个,需要复制32次# 第二种方式angles_interp = np.interp(x_index, xp_index, angles).astype(np.float32)if angles[0] > angles[-1]:  # 出现了角度的转折点# replace_angle = np.linspace(0,20,32) # 针对从360跳变到20 的角度替换change_index = np.argmax(angles)replace_index = change_index * 32 + 1interp_num_2 = int(angles[change_index+1]*32/40)  # 每个UDP数据包之间的角度间隔为 40,每个包有32条线;interp_num_1 = 32 - interp_num_2replace_angle_1 = np.linspace(angles[change_index], 35999, interp_num_1)  # 针对从360跳变到 20 的角度替换replace_angle_2 = np.linspace(0, angles[change_index+1],   interp_num_2)  # 针对从360跳变到 20 的角度替换angles_interp[replace_index:(replace_index+interp_num_1)] = replace_angle_1angles_interp[(replace_index+interp_num_1):(replace_index+32)] = replace_angle_2distances = distances * DISTANCE_RESOLUTIONx = distances * thetas_point_cos * np.sin(angles_interp)y = distances * thetas_point_cos * np.cos(angles_interp)z = distances * thetas_point_sinraw_points = np.stack((x, y, z), axis=1).astype(np.float32)# raw_points = np.stack((distances, angles_interp, refs, ), axis=1)   # 也可以只要原始数据print(type(x))print(len(x)) #384一组 每个udp384一组#print(x)return raw_pointsdef main(file_path):# f = open(file_path)          # 此写法为python2之下,f = open(file_path, mode='rb') #python3try:pcap = dpkt.pcap.Reader(f)  # 先按.pcap格式解析,若解析不了,则按pcapng格式解析except:print("it is not pcap ... format, pcapng format...")pcap = dpkt.pcapng.Reader(f)# 接下来就可以对pcap做进一步解析了,记住在使用结束后最好使用f.close()关掉打开的文件,虽然程序运行结束后,# 系统会自己关掉,但是养成好习惯是必不可少的。当前变量pcap中是按照“间戳:单包”的格式存储着各个单包# 将时间戳和包数据分开,一层一层解析,其中ts是时间戳,buf存放对应的包all_pcap_data = collections.OrderedDict()  # 有序字典# all_pcap_data_hex = collections.OrderedDict()  # 有序字典,存十六进制形式cir_point = []i = 1for (ts, buf) in pcap:try:eth = dpkt.ethernet.Ethernet(buf)  # 解包,物理层if not isinstance(eth.data, dpkt.ip.IP):  # 解包,网络层,判断网络层是否存在,continueip = eth.data# if not isinstance(ip.data, dpkt.tcp.TCP):  # 解包,判断传输层协议是否是TCP,即当你只需要TCP时,可用来过滤#     continueif not isinstance(ip.data, dpkt.udp.UDP):#解包,判断传输层协议是否是UDPcontinuetransf_data = ip.data  # 传输层负载数据,基本上分析流量的人都是分析这部分数据,即应用层负载流量if not len(transf_data.data):  # 如果应用层负载长度为0,即该包为单纯的tcp包,没有负载,则丢弃continueif len( transf_data.data) != 1206:  # 长度过滤   todo 为什么会有512字节的数据continueall_pcap_data[ts] = transf_data.data  # 将时间戳与应用层负载按字典形式有序放入字典中,方便后续分析.points = unpack_udp(transf_data.data)if i % 76 != 0:  # vlp16 每75个UDP数据包形成一圈数据cir_point.append(points)else:cir_udp = np.vstack(cir_point)print(cir_udp.shape)            # 最后需要的一圈完整的点云数据 只包含了28000余个xyz坐标cloud_all = pcl.PointCloud(cir_udp[:, 0:3].astype(np.float32))   # 可视化viewer.AddPointCloud(cloud_all)viewer.SpinOnce(100)viewer.RemoveAllPointClouds(0)cir_point = []i += 1except Exception as err:print( "[error] %s" % err)f.close()if __name__ == '__main__':#file_path="D:xxxxxx.pcap"file_path = "2020-10-21-10-13-57_Velodyne-VLP-16-Data.pcap"main(file_path)

这里其实都是数据格式解析,要知道怎么样的数据格式,用什么方式能够更好的解析。
当然好的工具使用起来也是很舒服,感谢开发这些库的大佬们。


总结

本文仅仅简单介绍了基于python的不同类型点云数据读取、显示方法,这些都比较简单。
ubuntu下一般都是录制bag 文件,并通过rviz显示,后续可以扩展一下。

第二章 python-pcl、open3d读取、显示pcd、bin等格式点云数据相关推荐

  1. 【python第一章 基础捋顺,第二章 python基础语法】

    第一章 基础捋顺,第二章 python基础语法 第一章 基础捋顺 第二章 python基础语法 2.1输入输出 2.2代码注释 2.3代码缩进 2.4命名规范 2.5变量 2.6基本数据类型 2.7数 ...

  2. 第二章 python系统监控

    第二章 python系统监控 用Python来编写脚本简化日常的运维工作是Python的一个重要用途.在Linux下,有许多系统命令可以让我们时刻监控系统运行的状态,如ps,top,free等等.要获 ...

  3. Python面试宝典(第二章 Python基础)

    Python面试宝典(第二章 Python基础) Python面试宝典(第二章 Python基础) 基础语法 输入输出 问题:代码中要修改不可变数据会出现什么问题? 抛出什么异常? 问题:a=1,b= ...

  4. 数字图像处理:第二章 图象获取、显示、表示与处理

    第二章 图象获取.显示.表示与处理 图象获取是图象的数字化过程,显示则是将数字图象转化为适合人们使用的形式,而处理是通过软件对图象进行变换操作的过程. 目录 图象获取 图象显示 图象表示 图象处理 参 ...

  5. 2的10次方-1的python表达式_第二章PythonⅠ的基本语法,python,I

    第二章 python基本语法 I 整数 交换两个变量的值 num1 = 10 num2 = 15 ##常规蛇形变换 tmp = num1 num1 = num2 num2 = tmp ##python ...

  6. python语言中、用来表示赋值的符号是_第二章Python语言基础知识

    第二章Python语言基础知识 2.1 Python语言基础知识 2.1.1标识符与关键字 在Python语言中,对程序中各个元素命名加以区分,这种用来标识变量.函数.类等元素的符号称为标识符. Py ...

  7. python pandas库读取excel/csv中指定行或列数据详解

    通过阅读表格,可以发现Pandas中提供了非常丰富的数据读写方法,下面这篇文章主要给大家介绍了关于python利用pandas库读取excel/csv中指定行或列数据的相关资料,需要的朋友可以参考下 ...

  8. python程序格式框架的描述_python 程序语言设计(嵩天)-学习笔记(第二章python 程序实例解析)...

    第 2 章 python 程序实例解析 学习目标: 掌握解决计算问题的一般方法. 掌握python语言的基本语法,包括缩进.变量.命名等. 掌握python语言绘制图形的一般方法. 了解python标 ...

  9. 第二章 Python语言基本语法元素

    文章目录 1.基本的语法元素 缩进 注释 续行符 2.变量 变量 常量 赋值语句 标识符 保留字 3.print()输出函数 1.基本的语法元素 缩进 1)Python语言采用严格的"缩进& ...

最新文章

  1. js 读取flask后台变量
  2. 初始python(二)
  3. php5(isapi).mysql5.zendforiis.rar_WIN2003系统IIS下PHP5+MySQL5+ZendOptimizer配置图解教程第1/3页...
  4. 报告解读丨细数万亿企服市场发展史,揭秘行业发展新趋势
  5. sqlite mysql pgsql_SQLite 、MySQL 与PostgreSQL三个关系型数据库的比较
  6. python拟合曲线的方式,Python实现曲线拟合操作示例【基于numpy,scipy,matplotlib库】...
  7. 修改itunes备份路径的方法(奇奇怪怪的文件堆积C盘,别让文件成为最后的稻草哦)
  8. conn.execute
  9. python编写makefile_Python项目中的Makefiles
  10. 再谈CentOS 7程序自启动
  11. LINUX编译OPENJDK:--with-target-bits can only 32 or 64, you specified 64
  12. 颜色列表(中英文名称,RGB HSV CMYK值)
  13. stellarium-0.19.3.1-win64.exe下载
  14. spark编程ERROR01——java.lang.NullPointerException
  15. 百度、快手、商汤、旷视等重磅嘉宾确认出席AI ProCon 2019,你还剩1天早鸟票特权!...
  16. python 最速曲线
  17. 服务器系统和操作系统的区别
  18. CloudComparePCL 点云点匹配(基于点到面的距离)
  19. Nomad 服务编排
  20. 工具 网络游戏封包基础

热门文章

  1. Hbuilder引用css文件无效
  2. 行车记录仪程序源码设计文档
  3. 优图实验室升级为腾讯计算机视觉研发中心,与 Science 期刊达成战略合作
  4. 测试封装的ftp客户端——Cftp类
  5. React 开发环境的搭建 (React脚手架)
  6. EOJ1600公路巡逻
  7. Python课设实验 之 爬虫应用——校园网搜索引擎(使用bs4进行数据分析.)
  8. WebTrust是什么?WebTrust认证的CA有哪些?
  9. MIL边缘检查实战2.0 20220307
  10. SQL注入攻击及其防范检测技术研究