目录
点云转深度图 测试ok:
远处白色,物体黑色,效果更好:
lidars=glob.glob(clip_dir+'/lidar/*.pcd')
lidars=natsorted(lidars)
img_width=3840
img_height=2160
for frame_id,lidar_path in enumerate(lidars):
print('lidar------------',frame_id)
pts_3d = []
pts_2d = []
pcd = o3d.io.read_point_cloud(lidar_path)
# 转换点云为 NumPy 数组
points = np.asarray(pcd.points)
pts_3d.append(points[:, :3])
# pts_3d_to_2d=pts_3d @ lidar2vcs @np.linalg.inv(cam2vcs).T @ K_4x4.T
points_2d= np.hstack((points, np.ones((points.shape[0], 1))))@np.linalg.inv(cam2vcs).T @ K_4x4.T
if 1:
points_2d[:,[0,1]]/=points_2d[:,[2]]
depth = points_2d[:, 2] # 深度值
# 创建深度图,并将所有点初始化为最大深度(如无穷远)
depth_map = np.full((img_height, img_width), np.inf)
# 将点云投影到像素坐标
w = points_2d[:, 0].astype(int)
h = points_2d[:, 1].astype(int)
# 过滤点,使得 w 和 h 在图像范围内
mask = np.logical_and.reduce((w >= 0, w < img_width, h >= 0, h < img_height))
w, h, depth = w[mask], h[mask], depth[mask]
# 逐像素赋值深度(最近点优先)
for i in range(len(w)):
if depth_map[h[i], w[i]] > depth[i]:
depth_map[h[i], w[i]] = depth[i]
# 将无穷远的像素设为最大深度值
max_depth = np.max(depth_map[np.isfinite(depth_map)])
depth_map[~np.isfinite(depth_map)] = max_depth
# 归一化到 0-255 并转换为 uint8
depth_map = (255 * (depth_map / max_depth)).astype(np.uint8)
cv2.imwrite(f'{cur_show_dir}/depth_{frame_id}.png', depth_map)
越远越黑:
lidars=glob.glob(clip_dir+'/lidar/*.pcd')
lidars=natsorted(lidars)
img_width=3840
img_height=2160
for frame_id,lidar_path in enumerate(lidars):
print('lidar------------',frame_id)
pts_3d = []
pts_2d = []
pcd = o3d.io.read_point_cloud(lidar_path)
# 转换点云为 NumPy 数组
points = np.asarray(pcd.points)
pts_3d.append(points[:, :3])
# pts_3d_to_2d=pts_3d @ lidar2vcs @np.linalg.inv(cam2vcs).T @ K_4x4.T
points_2d= np.hstack((points, np.ones((points.shape[0], 1))))@np.linalg.inv(cam2vcs).T @ K_4x4.T
if 1:
points_2d[:,[0,1]]/=points_2d[:,[2]]
depth = points_2d[:, 2] # 深度值
# 创建深度图,并将所有点初始化为最大深度(如无穷远)
depth_map = np.full((img_height, img_width), np.inf)
# 将点云投影到像素坐标
w = points_2d[:, 0].astype(int)
h = points_2d[:, 1].astype(int)
# 过滤点,使得 w 和 h 在图像范围内
mask = np.logical_and.reduce((w >= 0, w < img_width, h >= 0, h < img_height))
w, h, depth = w[mask], h[mask], depth[mask]
# 逐像素赋值深度(最近点优先)
for i in range(len(w)):
if depth_map[h[i], w[i]] > depth[i]:
depth_map[h[i], w[i]] = depth[i]
# 将无穷远的像素设为最大深度值
max_depth = np.max(depth_map[np.isfinite(depth_map)])
depth_map[~np.isfinite(depth_map)] = 0
# 归一化到 0-255 并转换为 uint8
depth_map = (255 * (depth_map / max_depth)).astype(np.uint8)
cv2.imwrite(f'{cur_show_dir}/depth_{frame_id}.png', depth_map)
python open3d实现,待测
import open3d as o3d
import numpy as np
import cv2
# 加载点云数据
pcd = o3d.io.read_point_cloud("your_point_cloud_file.ply") # 替换为你的点云文件路径
# 设置相机内参
camera_intrinsics = o3d.camera.PinholeCameraIntrinsic(width=640, height=480, fx=525, fy=525, cx=320, cy=240)
# 设置相机外参(这里假设无旋转和平移)
R = np.eye(3) # 3x3 旋转矩阵(单位矩阵)
t = np.array([0, 0, 0]) # 3x1 平移向量(零向量)
# 创建变换矩阵
extrinsics = np.eye(4)
extrinsics[:3, :3] = R
extrinsics[:3, 3] = t
# 使用外参将点云转换到相机坐标系
pcd.transform(extrinsics)
# 将点云转换为深度图
depth_map = o3d.geometry.PointCloud.create_depth_image_from_point_cloud_with_intrinsics(
pcd, camera_intrinsics, depth_scale=1000.0, depth_trunc=3.0, stride=1
)
# 将深度图转换为NumPy数组
depth_image = np.asarray(depth_map)
# 将深度图归一化到0-255并转换为8位图像
depth_image = cv2.normalize(depth_image, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)
# 使用 OpenCV 显示深度图
cv2.imshow("Depth Image", depth_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 保存深度图
cv2.imwrite("depth_image.png", depth_image)
pcl 三维数据的获取方式
RGBD相机和深度图
代码展示:在pcl中,把点云转为深度图,并保存和可视化
三维数据的获取方式
在计算机视觉和遥感领域,点云可以通过四种主要的技术获得,
(1)根据图像衍生而得,比如通过双目相机,
(2)基于RGBD相机获取点云
(3)基于光探测距离和测距系统比如lidar,
(4)Synthetic Aperture Radar (SAR)系统获取,基于这些不同的原理系统获取的点云数据,其数据的特征和应用的范围也是多种多样
RGBD相机和深度图
(1)深度图的原理:用深度值z值 当作像素值
(2)深度图获取原理:


代码展示:在pcl中,把点云转为深度图,并保存和可视化
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/common/common_headers.h>
#include <pcl/range_image/range_image.h> //点云转深度头文件
#include <pcl/visualization/range_image_visualizer.h> //深度图像可视化
#include <pcl/visualization/pcl_visualizer.h>//点云可视化
#include <boost/thread/thread.hpp>//多线程
#include <pcl/io/png_io.h>//保存深度图像
#include <pcl/visualization/common/float_image_utils.h>//保存深度图像
int main(int argc, char** argv) {
pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile("D:/zmy_719/vs_pcl/bun0.pcd", *pointCloud);
//以1度为角分辨率,从上面创建的点云创建深度图像。
//深度图像中的一个像素对应的角度大小1°,角度转弧度
float angularResolution = (float)(1.0f * (M_PI / 180.0f));
// 360.0度转弧度,扫描的水平宽度是360°
float maxAngleWidth = (float)(360.0f * (M_PI / 180.0f));
// 180.0度转弧度,扫描的垂直高度是180°
float maxAngleHeight = (float)(180.0f * (M_PI / 180.0f));
//采集位置,传感器的初始位姿
Eigen::Affine3f sensorPose = (Eigen::Affine3f)Eigen::Translation3f(0.0f, 0.0f, 0.0f);
//选择的系统 X轴是向右,Y轴向下,Z轴向前
//如果选择是LASER_FRAME,则X轴向前,Y轴向左,Z轴向上
pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME;
//noiseLevel如果设置为0.05就是5cm为半径的圆内的所有点的平均值,得到的深度值为准
float noiseLevel = 0.00;
//minRange大于0,假设为r,那么r内的所有点被忽略,为盲区
float minRange = 0.0f;
int borderSize = 1;
//-------------------生成深度图像------------------------
pcl::RangeImage::Ptr rangeImage_ptr(new pcl::RangeImage);
pcl::RangeImage& rangeImage = *rangeImage_ptr;
rangeImage.createFromPointCloud(*pointCloud, angularResolution, maxAngleWidth, maxAngleHeight, sensorPose, coordinate_frame, noiseLevel, minRange, borderSize);
//-------------------读取深度图像信息------------------------
std::cout << rangeImage << "\n";
//-------------------深度图的保存------------------------
float* ranges = rangeImage.getRangesArray();
unsigned char* rgb_image = pcl::visualization::FloatImageUtils::getVisualImage(ranges, rangeImage.width, rangeImage.height);
pcl::io::saveRgbPNGFile("RangeImage.png", rgb_image, rangeImage.width, rangeImage.height);
//------------------可视化点云----------------------
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer1(new pcl::visualization::PCLVisualizer("PointCloud Viewer"));
//设置背景颜色
viewer1->setBackgroundColor(0, 0, 0);
//添加点云
viewer1->addPointCloud(pointCloud, "point cloud");
viewer1->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 0, 1, "point cloud");
viewer1->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "point cloud");
//------------------可视化深度图像----------------------
//方法一:从点云中可视化深度图像
boost::shared_ptr<pcl::visualization::PCLVisualizer>viewer(new pcl::visualization::PCLVisualizer("RangeImage Viewer"));
viewer->setBackgroundColor(0, 0, 0); //设置背景颜色为黑色
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointWithRange> range_image_color_handler(rangeImage_ptr, "z");
viewer->addPointCloud(rangeImage_ptr, range_image_color_handler, "range image");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "range image");
viewer->initCameraParameters();
//方法二:以图像的形式显示深度图像,深度值作为颜色显示
pcl::visualization::RangeImageVisualizer range_image_widget("Range image");
range_image_widget.setWindowTitle("RangeImage");
range_image_widget.showRangeImage(rangeImage);
range_image_widget.setSize(1000, 1000);
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
system("pause");
return 0;
}
结果展示:



代码参考:PCL官网
原文链接:https://blog.csdn.net/adfjadsklf/article/details/119082844

该博客介绍了如何使用PCL库将点云数据转换为深度图并进行保存及可视化。通过RGBD相机获取的点云数据,可以利用PCL的RangeImage类创建深度图,并通过保存深度图像的RGB PNG文件实现存储。同时,提供了两种方法在PCL可视化器中展示深度图像,一是直接从点云中可视化,二是以图像形式展示深度值。
1950

被折叠的 条评论
为什么被折叠?



