目录
1.RGBD2Point
input:RGB + D + 内外惨
output:points cloud
def depth2pcd(depth_img):
"""
深度图转点云数据
图像坐标系 -> 世界坐标系
:param depth_img: 深度图
:return: 点云数据 N*3
"""
# 相机内参
cam_fx = 1120.12
cam_fy = 1120.12
cam_cx = 640.5
cam_cy = 360.5
factor = 1
# 逐点处理,此过程可以使用numpy优化
m, n = depth_img.shape
point_cloud = []
for v in range(m):
for u in range(n):
if depth_img[v, u] == 0:
continue
depth = depth_img[v, u]
p_z = depth / factor z = 深度/焦距
p_x = (u - cam_cx) * p_z / cam_fx
p_y = (v - cam_cy) * p_z / cam_fy
point_cloud.append([p_x, p_y, p_z]) # 这里还可以添加RGB信息
point_cloud = np.array(point_cloud)
return point_cloud
1.2 步骤
RGBD数据转换为点云的过程通常包括以下步骤:
-
从深度图像中提取点云坐标:使用深度图像中的像素值计算每个像素在三维空间中的坐标。这可以通过将深度值转换为相机坐标系下的坐标来实现。 (X,Y,Z)
-
确定相机内参和外参:相机内参包括相机的焦距、主点和畸变参数等,用于将像素坐标转换为相机坐标系下的坐标。相机外参包括相机在世界坐标系下的位置和方向,用于将相机坐标系下的坐标转换为世界坐标系下的坐标。
-
将深度图像转换为点云坐标:对于每个像素,根据其深度值和相机内参,可以计算出其在相机坐标系下的坐标。然后,根据相机外参,可以将相机坐标系下的坐标转换为世界坐标系下的坐标。这样就可以得到每个像素对应的点云坐标。
-
去除无效点:深度图像中可能包含一些无效点,例如深度值为0或超出一定范围的点。这些点需要被去除,以保证点云的质量和准确性。
-
可选:对点云进行滤波和重采样:为了减少噪声和数据量,可以对点云进行滤波和重采样。例如,可以使用高斯滤波或中值滤波来平滑点云,或使用体素格化和统计滤波来降低点云的密度。
-
-
从RGB图像中提取点云颜色:使用RGB图像中的像素值提取每个点的颜色信息。这可以通过将RGB值与对应的点云坐标进行匹配来实现。 (X,Y, Z,R,G,B)
-
确定相机内参和外参:与从深度图像中提取点云坐标类似,从RGB图像中提取点云颜色也需要相机内参和外参的信息。
-
将RGB图像转换为点云颜色:对于每个点云坐标,可以使用相机内参和外参将其对应到RGB图像上的像素坐标。然后,可以从RGB图像中提取对应像素的颜色信息,例如RGB值或HSV值等。
-
可选:对颜色进行校正和增强:为了提高颜色的准确性和鲁棒性,可以对颜色进行校正和增强。例如,可以使用颜色校正矩阵来校正颜色偏差,或使用直方图均衡化和对比度增强来增强颜色对比度。
-
-
将点云坐标和颜色信息组合成点云:将每个点的坐标和颜色信息组合成一个点云。这可以通过将坐标和颜色信息存储在一个结构体或数组中来实现
2.Point2Voxel-Voxelization
2.1 原理
将点云数据转换为体素(voxel)通常需要进行以下步骤:
-
确定体素大小和边界:体素大小是指体素的边长,它决定了体素的分辨率和精度。边界是指点云数据的空间范围,它决定了体素的数量和大小。
-
将点云数据转换为体素坐标:对于每个点云坐标,可以根据体素大小将其对应到体素坐标系下的坐标。例如,可以将点云坐标除以体素大小并向下取整,以得到其对应的体素坐标。
-
将点云数据分配到体素中:对于每个体素坐标,可以将其对应的点云数据分配到该体素中。例如,可以将该体素中所有点云数据的颜色或法向量进行平均或加权平均,以得到该体素的颜色或法向量信息。
-
可选:对体素进行滤波和重采样:为了减少噪声和数据量,可以对体素进行滤波和重采样。例如,可以使用高斯滤波或中值滤波来平滑体素,或使用体素格化和统计滤波来降低体素的密度。
转换后的体素数据可以用于各种计算机视觉和机器学习任务,例如三维重建、物体识别和姿态估计等。
2.2 代码
import numpy as np
from scipy.spatial import cKDTree
def pointcloud_to_voxel(pointcloud, voxel_size):
# 计算体素边界和数量
min_bound = np.min(pointcloud, axis=0)
max_bound = np.max(pointcloud, axis=0)
voxel_count = np.ceil((max_bound - min_bound) / voxel_size).astype(int)
# 将点云数据转换为体素坐标
voxel_coords = np.floor((pointcloud - min_bound) / voxel_size).astype(int)
# 将点云数据分配到体素中
voxel_data = np.zeros(voxel_count + 1)
for i in range(len(pointcloud)):
voxel_data[tuple(voxel_coords[i])] += 1
# 可选:对体素进行滤波和重采样
# ...
return voxel_data
3.Voxel2Point
将3D体素数据转换为点云数据通常需要进行以下步骤:
以下是一个简单的Python代码示例,用于将点云数据转换为RGB图像:
-
确定体素大小和边界:体素大小是指体素的边长,它决定了体素的分辨率和精度。边界是指3D体素数据的空间范围,它决定了体素的数量和大小。
-
遍历体素数据,将非空体素转换为点云数据:对于每个非空体素,可以将其转换为一个或多个点云数据。例如,可以将该体素的中心点作为点云数据,或者将该体素中所有非空体素的中心点作为点云数据。
-
可选:对点云数据进行滤波和重采样:为了减少噪声和数据量,可以对点云数据进行滤波和重采样。例如,可以使用高斯滤波或中值滤波来平滑点云数据,或使用体素格化和统计滤波来降低点云数据的密度。
-
import numpy as np def voxel_to_pointcloud(voxel_data, voxel_size): # 计算体素边界和数量 min_bound = np.array([0, 0, 0]) max_bound = np.array(voxel_data.shape) * voxel_size # 遍历体素数据,将非空体素转换为点云数据 pointcloud = [] for x in range(voxel_data.shape[0]): for y in range(voxel_data.shape[1]): for z in range(voxel_data.shape[2]): if voxel_data[x, y, z] > 0: pointcloud.append([x * voxel_size, y * voxel_size, z * voxel_size]) # 可选:对点云数据进行滤波和重采样 # ... return np.array(pointcloud)
4.Point2RGB
将点云数据转换为RGB图像通常需要进行以下步骤:
-
确定图像大小和分辨率:图像大小是指图像的宽度和高度,它决定了图像的分辨率和精度。分辨率是指图像中每个像素的大小,通常以像素/英寸(PPI)或像素/厘米(PPC)为单位。
-
将点云数据转换为图像坐标:对于每个点云坐标,可以根据图像大小和分辨率将其对应到图像坐标系下的坐标。例如,可以将点云坐标乘以分辨率并向下取整,以得到其对应的图像坐标。
-
将点云数据分配到图像中:对于每个图像坐标,可以将其对应的点云数据分配到该像素中。例如,可以将该像素中所有点云数据的颜色进行平均或加权平均,以得到该像素的颜色信息。
-
可选:对图像进行滤波和增强:为了减少噪声和提高图像质量,可以对图像进行滤波和增强。例如,可以使用高斯滤波或中值滤波来平滑图像,或使用直方图均衡化和对比度增强来增强图像对比度。
import numpy as np import cv2 def pointcloud_to_rgb(pointcloud, image_size, resolution): # 确定图像大小和分辨率 image_width, image_height = image_size pixel_size = 1 / resolution # 将点云数据转换为图像坐标 image_coords = np.floor((pointcloud[:, :2] * resolution)).astype(int) # 将点云数据分配到图像中 image_data = np.zeros((image_height, image_width, 3)) for i in range(len(pointcloud)): x, y = image_coords[i] image_data[y, x] += pointcloud[i, 2:] # 可选:对图像进行滤波和增强 # ... # 将图像数据转换为RGB图像 image_data = (image_data / np.max(image_data) * 255).astype(np.uint8) rgb_image = cv2.cvtColor(image_data, cv2.COLOR_BGR2RGB) # 可选:使用OpenCV显示图像 cv2.imshow('RGB Image', rgb_image) cv2.waitKey(0) cv2.destroyAllWindows() return rgb_image
5.Voxel2RGB
将3D体素数据转换为2D图像通常需要进行以下步骤:
-
确定投影方向和投影平面:投影方向是指将3D体素数据投影到2D图像的方向,通常是x、y或z轴方向。投影平面是指投影方向所在的平面,通常是与另外两个轴垂直的平面。
-
将3D体素数据投影到2D图像:对于每个投影平面上的像素,可以将其对应到3D体素数据中的体素坐标。然后,可以根据投影方向和投影平面,将该体素沿着投影方向上的值投影到2D图像上的像素值中。例如,可以将该体素的最大值或平均值作为该像素的像素值。
-
可选:对2D图像进行滤波和增强:为了减少噪声和提高图像质量,可以对2D图像进行滤波和增强。例如,可以使用高斯滤波或中值滤波来平滑图像,或使用直方图均衡化和对比度增强来增强图像对比度。
-
import numpy as np import cv2 def voxel_to_image(voxel_data): # 确定投影方向和投影平面 proj_axis = 2 proj_plane = np.delete(np.arange(3), proj_axis) # 将3D体素数据投影到2D图像 proj_data = np.max(voxel_data, axis=proj_axis) proj_data = np.transpose(proj_data, axes=proj_plane) # 可选:对2D图像进行滤波和增强 # ... # 将2D图像转换为灰度图像 proj_data = (proj_data / np.max(proj_data) * 255).astype(np.uint8) # 可选:使用OpenCV显示图像 cv2.imshow('Projection', proj_data) cv2.waitKey(0) cv2.destroyAllWindows() return proj_data