AVOD:点云数据与BEV图的处理及可视化

article/2025/11/7 7:32:17

文章目录

    • 前言
    • 1. 点云数据可视化
    • 2. 点云数据校准
    • 3. 转为BEV图
    • 4. 补充:点云坐标系与相机坐标系
    • 结束语

前言

  本篇主要记录对AVOD代码的学习与理解,主要是KITTI数据集中3D Object Detection任务中的点云数据和BEV图的处理,为方面理解其中的操作,博主在这里加入了可视化的操作。

  本篇博客使用的样本编号为000274RGB图像如下:

在这里插入图片描述

1. 点云数据可视化

  点云数据保存在velodyne文件夹内,数据文件的格式是.bin,保存了x, y, z三轴坐标以及反射值r信息,数据格式为float32,通过numpy可以读取文件,具体如下:

import numpy as npif __name__ == '__main__':bin_file = r'F:\DataSet\Kitti\object\velodyne\000274.bin'pointcloud = np.fromfile(bin_file, dtype=np.float32, count=-1).reshape([-1, 4])print('pointcloud shape: ', pointcloud.shape)# pointcloud shape:  (120438, 4)

  为了更加直观的看点云图像,这里不再使用matplotlib,而是更专业的三维可视化工具包mayavi,具体操作如下:

import numpy as np
from mayavi import mlabif __name__ == '__main__':bin_file = r'F:\DataSet\Kitti\object\velodyne\000274.bin'pointcloud = np.fromfile(bin_file, dtype=np.float32, count=-1).reshape([-1, 4])x = pointcloud[:, 0]  # x position of pointy = pointcloud[:, 1]  # y position of pointz = pointcloud[:, 2]  # z position of pointr = pointcloud[:, 3]  # reflectance value of pointd = np.sqrt(x ** 2 + y ** 2)  # Map Distance from sensorvals = 'height'if vals == "height":col = zelse:col = dfig = mlab.figure(bgcolor=(1, 1, 1), size=(700, 500))mlab.points3d(x, y, z,d,  # Values used for Colormode="point",colormap='spectral',  # 'bone', 'copper', 'gnuplot', 'spectral', 'summer'# color=(0, 1, 0),   # Used a fixed (r,g,b) insteadfigure=fig)mlab.show()

  可视化结果如下:

在这里插入图片描述
  调整一下视角与RGB图保持一致:
在这里插入图片描述

2. 点云数据校准

  RGB图片使用的是左侧第二个彩色摄像机,即image_2,因此需要将雷达数据进行坐标变化,将其映射到摄像机坐标系中,计算公式为:

										y = P2 * R0_rect * Tr_velo_to_cam * x

  大致计算流程:

# Read calibration info
frame_calib = calib_utils.read_calibration(calib_dir, img_idx)
x, y, z, i = calib_utils.read_lidar(velo_dir=velo_dir, img_idx=img_idx)# Calculate the point cloud
pts = np.vstack((x, y, z)).T
pts = calib_utils.lidar_to_cam_frame(pts, frame_calib)# Only keep points in front of camera (positive z)
pts = pts[pts[:, 2] > 0]
point_cloud = pts.T# Project to image frame
point_in_im = calib_utils.project_to_image(point_cloud, p=frame_calib.p2).T

  具体实现:

# 为了方便可视化数据,这里封装了对点云进行可视化的函数
def visu_point_cloud(x, y, z):d = np.sqrt(x ** 2 + y ** 2)  # Map Distance from sensorvals = 'distance'if vals == "distance":col = delse:col = zfig = mlab.figure(bgcolor=(1, 1, 1), size=(700, 500))mlab.points3d(x, y, z,col,  # Values used for Colormode="point",colormap='spectral',  # 'bone', 'copper', 'gnuplot', 'spectral', 'summer'# color=(0, 1, 0),   # Used a fixed (r,g,b) insteadfigure=fig)mlab.show()def get_lidar_point_cloud(calib_dir, velo_dir, img_idx, im_size=None, min_intensity=None):""" Calculates the lidar point cloud, and optionally returns only thepoints that are projected to the image.:param calib_dir: directory with calibration files:param velo_dir: directory with velodyne files:param img_idx: image index:param im_size: (optional) 2 x 1 list containing the size of the imageto filter the point cloud [w, h]:param min_intensity: (optional) minimum intensity required to keep a point:return: (3, N) point_cloud in the form [[x,...][y,...][z,...]]"""# Read calibration infoframe_calib = read_calibration(calib_dir, img_idx)x, y, z, i = read_lidar(velo_dir=velo_dir, img_idx=img_idx)# Calculate the point cloudpts = np.vstack((x, y, z)).Tpts = lidar_to_cam_frame(pts, frame_calib)# The given image is assumed to be a 2D imageif not im_size:point_cloud = pts.Treturn point_cloudelse:# Only keep points in front of camera (positive z)pts = pts[pts[:, 2] > 0]point_cloud = pts.T# Project to image framepoint_in_im = project_to_image(point_cloud, p=frame_calib['p2']).T# Filter based on the given image sizeimage_filter = (point_in_im[:, 0] > 0) & \(point_in_im[:, 0] < im_size[0]) & \(point_in_im[:, 1] > 0) & \(point_in_im[:, 1] < im_size[1])if not min_intensity:return pts[image_filter].Telse:intensity_filter = i > min_intensitypoint_filter = np.logical_and(image_filter, intensity_filter)return pts[point_filter].Timg_path = r'F:\DataSet\Kitti\object\image_2'
lidar_path = r'F:\DataSet\Kitti\object\velodyne'
calib_path = r'F:\DataSet\Kitti\object\calib'
planes_path = r'F:\DataSet\Kitti\object\planes'
label_path = r'F:\DataSet\Kitti\object\label_2'
img_idx = 274if __name__ == '__main__':point_cloud = get_lidar_point_cloud(calib_path, lidar_path, img_idx, im_size)visu_point_cloud(point_cloud[0], point_cloud[1], point_cloud[2])

  可视化结果如下:

在这里插入图片描述
  调整视角为俯视图:

在这里插入图片描述

3. 转为BEV图

  BEV,即bird's eye view,鸟瞰图

  鸟瞰图的计算需要用到地面数据,即空间上的点投影到某个平面,需要知道该平面的平面方程,平面方程的表达式为: a x + b y + c z + d = 0 ax+by+cz+d=0 ax+by+cz+d=0  空间上的点 P ( x 0 , y 0 , z 0 ) P(x_0,y_0,z_0) P(x0,y0,z0)到平面上的距离为: d i s t a n c e = ∣ a x 0 + b y 0 + c z 0 + d ∣ a 2 + b 2 + c 2 distance=\frac {|ax_0+by_0+cz_0+d|} {\sqrt {a^2+b^2+c^2}} distance=a2+b2+c2 ax0+by0+cz0+d  读取KITTI数据集中的地面数据:

# 000274.txt
# Plane
Width 4
Height 1
-2.143976e-03 -9.997554e-01 2.201096e-02 1.707479e+00
# 分别表示a, b, c, d四个参数值

  点云数据转BEV时高度分辨率为0.5,根据点云数据可以得到xyz轴上的数据,即x_coly_colz_col,然后使用np.lexsort()x轴进行排序:

sorted_order = np.lexsort((y_col, z_col, x_col))
# 对 x_col 进行排序
# 如果 x_col 中的数值一样,则比较 z_col 中相应索引下的值的大小
# 如果还相同,再比较 y_col 中的元素

  将 y_col 中的元素置为0,即只保留xz轴上的数据,然后使用np.view()对数值类型进行变换:

# 定义12字节的数据类型
dt = np.dtype((np.void, 12))# 先使用np.ascontiguousarray将一个内存不连续存储的数组转换为内存连续存储的数组,使得运行速度更快
# 再使用np.view按指定方式对内存区域进行切割,来完成数据类型的转换
# discrete_pts(n, 3) --> contiguous_array(n, 1)
# itemsize输出array元素的字节数
contiguous_array = np.ascontiguousarray(discrete_pts).view(dtype=dt)

  离散点云数据discrete_ptsshape(n,3),其数值类型为np.int324字节,总字节为n*3*4 Byte,现将其转为12Byte的数据,即保持总字节数不变:n*1*12,转换完成后的shape(n,1)

  对上述的数据进行去重:

# 去除数组中的重复数字,并进行排序
_, unique_indices = np.unique(contiguous_array, return_index=True)
unique_indices.sort()
# 得到不重复的数据
# voxel 体素(三维) 
# pixel 像素(二维)
voxel_coords = discrete_pts[unique_indices]
# 将索引值映射到原点
voxel_coords -= -400

  计算每个体素中数据点的数量,即后一个索引值减去当前索引值:

num_points_in_voxel = np.diff(unique_indices)
num_points_in_voxel = np.append(num_points_in_voxel,discrete_pts_2d.shape[0] -unique_indices[-1])

  计算每个体素中数据点的高度,通过计算点到平面方程的距离:

# voxel (x, y, z)
# 平面方程: ax + by + cz + d = 0
height_in_voxel = (a*x + b*y + c*z + d) / np.sqrt(a**2 + b**2 + c**2)

  对高度信息进行缩放,height_in_voxel = height_in_voxel / 0.5,根据二维索引值voxel_coords(去除y轴)与高度信息即可得到BEV数据,密度信息的计算:

# N is num points in voxel 
# x = 16
density_map = min(1.0, log(N+1)/log(x))

  最终的BEV是由5个高度信息和1个密度信息组成,其shape(700, 800, 6)
  三维可视化结果如下:

在这里插入图片描述
  RGB可视化如下:

在这里插入图片描述

4. 补充:点云坐标系与相机坐标系

  点云坐标系如下:

在这里插入图片描述

  x轴朝前,y轴朝左,z轴朝上。

  相机坐标系如下:

在这里插入图片描述

  x轴朝右,y轴朝下,z轴朝前。

  最终BEV的维度为:

在这里插入图片描述

结束语

  后续继续更新^_^


http://chatgpt.dhexx.cn/article/bQ0y1KRG.shtml

相关文章

视觉与激光雷达融合3D检测(一)AVOD

1.概述 AVOD&#xff08;Aggregate View Object Detection&#xff09;和MV3D类似,是一种融合3维点云和相机RGB图像的三维目标检测算法. 不同的是: MV3D中融合了相机RGB图像,点云BEV映射和FrontView映射,而AVOD则只融合相机RGB图像和点云BEV映射. 从网络结果来看,AVOD采用了基…

AVOD论文解读

AVOD论文解读 1.概述2.网络框架2.1 激光点云数据预处理2.2 特征提取2.3 降低数据量2.4 3D后选区域生成2.5 3D检测框编码2.6 朝向估计 论文地址&#xff1a;[1712.02294] Joint 3D Proposal Generation and Object Detection from View Aggregation (arxiv.org) 代码地址&#…

AVD的使用

前言&#xff1a;这个是AndroidStudio自带的模拟器&#xff0c;虽然功能强大&#xff0c;但是感觉不太好用&#xff0c;安装和使用都比较卡。 个人推荐使用夜神模拟器。 1.打开AndroidStudio&#xff0c;并新建一个工程 2.在菜单栏选择Tools-Android-AVDManager--Create Virt…

复现AVOD

复现过程主要参考https://zhuanlan.zhihu.com/p/87136172 这位博主 之前跟着官方github&#xff08;https://github.com/kujason/avod&#xff09; 环境一直配置不好&#xff0c;之后直接使用博主提供的yaml配置文件&#xff0c;之后进行略微调整即可 与博主不同的是&#xf…

AVOD-理解系列(一)

AVOD-理解 本篇用于记载之前阅读的论文avod及其代码&#xff0c;纯属个人个人理解&#xff0e;有误之处欢迎指正&#xff01; 网络结构 代码流程 1&#xff1a;Feed_dict: feed_dict: 主要就是确定每一个mini_batch里输入图像的各种信息,包括图像的名字,图像的标签文件,图像…

AVOD代码复现

参考文献&#xff1a; https://zhuanlan.zhihu.com/p/86340957 https://zhuanlan.zhihu.com/p/354842740 https://www.guyuehome.com/39798 https://zhuanlan.zhihu.com/p/40271319 1&#xff0c;配置环境 conda create -n avod python3.5 conda install tensorflow-gpu1.3.0…

三十三.智能驾驶之多传感器融合技术: AVOD融合方法

AVOD&#xff08;Aggregate View Object Detection&#xff09;和MV3D类似,是一种融合3维点云和相机RGB图像的三维目标检测算法. 不同的是: MV3D中融合了相机RGB图像,点云BEV映射和FrontView映射,而AVOD则只融合相机RGB图像和点云BEV映射. 从网络结果来看,AVOD采用了基于两阶的…

AVOD论文和代码解析

1.介绍 AVOD&#xff08;Aggregate View Object Detection&#xff09;算法和MV3D算法在思路上非常相似&#xff0c;甚至可以说&#xff0c;AVOD是MV3D的升级版本 总的来说&#xff0c;和MV3D相比&#xff0c;AVOD主要做了以下一些改进&#xff1a; &#xff08;1&#xff0…

论文阅读笔记 | 三维目标检测——AVOD算法

如有错误&#xff0c;恳请指出。 文章目录 1. 背景2. 网络结构3. 实验结果 paper&#xff1a;《Joint 3D Proposal Generation and Object Detection from View Aggregation》 1. 背景 AVOD同样是一个two-stage(使用了RPN提取候选框)、anchor-based网络结构。获得较高的召回率…

IC授权卡和复制卡的区别_信用卡小知识【芯片卡磁条卡的区别】

各位老板&#xff0c;企业家大家好&#xff0c;我是小胡&#xff0c;您身边的金融专家。 今天呢跟大家说一下信用卡芯片卡和磁条卡的区别&#xff1f; 信用卡呢&#xff0c;现在普及率非常高的。几乎是人手一张或者是多张。那么大家知道芯片卡和磁条卡的区别到底在哪里&#xf…

IC卡清卡软件的使用

IC卡清卡软件&#xff0c;可以在知道卡片密码的情况下&#xff0c;把卡片恢复出厂密码&#xff0c;清除卡片数据和密码。 如下图 然后读取卡片文件&#xff0c;即卡片dump文件&#xff0c; 然后把卡片放读写器上&#xff0c;点清卡按钮&#xff0c;开始清卡&#xff0c;将清除…

门禁 IC卡 和 ID卡初步了解

目录 一、常用卡介绍 二、复制加密IC卡 1. 工具 2. 方法 3. 最简单的办法 三、IC卡种类介绍 1、接触型IC卡 2、非接触型IC卡 3、串行传输型IC卡 4、并行传输型IC卡 5、存储型IC卡(Memory Card) 6、加密存储型IC卡(Memory Card With Security Logic) 7、智能…

@芯片IC卡也能被复制?冒名卡/克隆卡分分钟复制完成【威 要器妖酒寺起舞酒久吧尔救】

去年底&#xff0c;广西贺州法院审理了一起未成年人盗刷校园IC卡案。被告廖某将已充值的校园IC卡信息复制到另一张空白卡上&#xff0c;在校园内的食堂、超市等进行刷卡消费。并将此方式传给另外4名同乡伙伴&#xff0c;5人共计非法盗刷2万多元。 网购工具 操作简单 据被告廖某…

ID卡复制教程(使用T5577卡复制4100卡)

1 ID卡的常见类型与区别 国内常见的普通ID卡多为EM 4100 或 EM 4102卡&#xff0c;其特点是不可修改ID号。为了复制普通ID卡&#xff0c;通常采用T5577 或 EM4305卡&#xff08;俗称ID白卡&#xff09;&#xff0c;其特点是内部EEPROM可读可写&#xff0c;修改卡内EEPROM的内容…

教程:利用艾斯PM3GUI软件助手,帮你查IC卡漏洞

测试目的&#xff1a;检查身边的IC卡是否有技术漏洞&#xff08;门禁卡&#xff0c;会员卡&#xff09; 测试软件&#xff1a;艾斯PM3GUI软件助手2022版&#xff08;IC卡信息安全专家&#xff09;测试设备&#xff1a;PM3easy 优化增强版测试环境&#xff1a;Windows10 我们先拿…

华为手机NFC功能,教你一键复制各种卡

日常生活中&#xff0c;我们经常会携带各种卡&#xff0c;比如&#xff1a;公交卡、门禁卡、银行卡等&#xff0c;但是有时候忘记带了怎么办&#xff1f;或者带了却丢失了。 很多人都知道NFC功能支持充值公交卡&#xff0c;但是它的其他作用你还知道多少个&#xff0c;这期小编…

IC授权卡和复制卡的区别_北京居住证跟居住卡的区别

北京市居住证是小伙伴们在北京居住、作为常住人口享受基本公共服务和便利、通过积分申请登记常住户口的证明。持有居住证就是在京享受基本公共服务和便利的基础,居住登记卡是申领居住证的基础。按照北京市相关规定,在到达北京3日内,小伙伴应主动申报暂住登记,领取居住登记卡…

蓝牙卡复制html,车库蓝牙卡能复制吗

现在小区为了业主小车的安全会在车库上安装门禁系统。那么车库蓝牙卡能复制吗?车库蓝牙卡怎么复制呢&#xff1f;下面就跟着小编一起来看看吧&#xff01; 车库蓝牙卡能复制吗&#xff1a; 车库蓝牙卡能复制&#xff0c;价格一般在30-60元左右&#xff0c;复制的蓝牙卡与原版外…

普通门禁卡及各类复制卡相关知识

转自&#xff1a; https://nfctool.cn/42 本文带你了解M1卡的数据结构&#xff0c;为以后的破解提供理论基础。同时带你了解各种IC卡&#xff0c;让你对破解和复制有更清晰的目标。请注意&#xff0c;ID卡没有密码&#xff0c;一读一写即可复制&#xff0c;手机手环不能模拟ID卡…

IC卡与ID卡

IC卡与ID卡定义 IC卡全称集成电路卡&#xff08;Integrated Circuit Card&#xff09;&#xff0c;又称智能卡&#xff08;Smart Card&#xff09;它是将一个微电子芯片嵌入符合ISO 7816标准的卡基中&#xff0c;做成卡片形式&#xff0c;芯片含的存储器&#xff08;ROM、EEPR…