PCL将深度图转化为点云并存储为pcd文件

使用OpenCV4和PCL1.9实现深度图像转点云图像 一、参考高翔博士的一起做RGB-D SLAM (2),针对在高版本环境下编译出现错误,做以下两点修改 1、读入图像路径 rgb =cv::imread("./data/rgb.png"); depth =cv::imread("./data/depth.png", -1); 修改为 rgb =cv::imread("../data/rgb.png"); depth =cv::imread("../data/depth.png", -1); 2、针对在gcc 5.4.0版本下编辑不通过, 阅读详情
AI摘要

博客记录点云基础知识,包括深度相机采集的depth数据转换为点云pcd,需相机内参数据;还介绍用pcl写点云数据到pcd文件,以ASCII码形式写入,写速慢、文件大但可用文本查看坐标,以二进制形式写入,写速快、文件小,打开是乱码。

最近又开始折腾点云了,下面记录一点基础知识。
(1)深度相机采集的depth 数据如何转换为点云pcd
一般3D相机都会采集到depth 数据,以记录深度相机拍摄到的深度距离Z值。要将深度图转化成三维空间点云数据,首先需要相机的内参数据。
示例如下:

#include <iostream>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/registration/icp.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/registration/ndt.h>

#include <windows.h>


// 定义点云类型(不带颜色)
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloud;

//---------相机内参---------------
const double camera_factor = 1000;//单位米
const double camera_fx = 611.716003; ;
const double camera_fy = 612.044861;
const double camera_cx = 631.656372; 
const double camera_cy = 401.639801; 
bool CreateDirectorySimple(const std::string& dir) 
{
	return CreateDirectoryA(dir.c_str(), NULL) || GetLastError() == ERROR_ALREADY_EXISTS;
}

std::vector<std::string> FindAllPngDepthImages(const std::string& image_dir) 
{
	std::vector<std::string> png_files;

	WIN32_FIND_DATAA find_data;
	HANDLE hFind = INVALID_HANDLE_VALUE;
	std::string pattern = image_dir + "*.png";

	hFind = FindFirstFileA(pattern.c_str(), &find_data);
	if (hFind == INVALID_HANDLE_VALUE) {
		std::cerr << "无法打开目录或未找到 PNG 文件: " << image_dir << std::endl;
		return png_files;
	}

	do {
		std::string filename = find_data.cFileName;

		// 排除目录
		if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			continue;

		// 添加 PNG 文件路径
		png_files.push_back(image_dir + filename);

	} while (FindNextFileA(hFind, &find_data) != 0);

	FindClose(hFind);
	return png_files;
}

bool ProcessDepthImage(const std::string& depth_path, const std::string& pcd_path) 
{
	// 读取深度图像
	std::cout << "找到 " << depth_path << std::endl;
	cv::Mat depth = cv::imread(depth_path, cv::IMREAD_UNCHANGED);
	if (depth.empty()) 
	{
		std::cerr << "无法加载深度图像: " << depth_path << std::endl;
		return false;
	}
	// 检查深度图像类型
	if (depth.type() != CV_16UC1 && depth.type() != CV_32FC1) {
		std::cerr << "深度图像类型不支持 (仅支持 CV_16UC1 和 CV_32FC1): " << depth_path << std::endl;
		return false;
	}
	// 创建点云对象
	PointCloud::Ptr cloud(new PointCloud);
	// 定义圆柱体过滤参数
	const double target_z = 0.97; // 目标距离1米
	const double z_tolerance = 0.5;// 深度容忍范围 ±0.05米
	const double radius = 0.65;//    // 圆柱体半径0.5米(直径1米)
	// 遍历每个像素
	for (int m = 0; m < depth.rows; m++)
	 {
		for (int n = 0; n < depth.cols; n++) 
		{
			// 获取深度值
			unsigned short d = depth.ptr<unsigned short>(m)[n];
			if (d == 0)
				continue; // 无效深度值,跳过
			// 计算空间坐标(单位:米)
			double z = double(d) / camera_factor;
			double x = (n - camera_cx) * z / camera_fx;
			double y = (m - camera_cy) * z / camera_fy;

			// --------过滤条件:提取位于指定ROI范围内的点云数据
			if (x <- 0.65)
				continue;
			if (sqrtf((z - target_z)*(z - target_z)+ (y-0.034) * (y - 0.034) ) > (radius * radius))//圆柱体过滤
			continue;
			
			// 创建点
			PointT p;
			p.x =  (x);
			p.y =  (y);
			p.z =  (z);			
			// 添加到点云
			cloud->points.push_back(p);
		}
	}
	// 设置点云属性
	cloud->height = 1;
	cloud->width = static_cast<uint32_t>(cloud->points.size());
	cloud->is_dense = false;
	std::cout << "点云大小 = " << cloud->points.size() << std::endl;
	if(cloud->points.size() == 0)  		
		return false;
	// 保存 PCD 文件
	//if (pcl::io::savePCDFileASCII(pcd_path, *cloud) == -1)//以ASCII 码形式吸入pcd
	if (pcl::io::savePCDFileBinary(pcd_path, *cloud) == -1)//以二进制形式写入pcd
	{
		PCL_ERROR("无法保存 PCD 文件: %s\n", pcd_path.c_str());
		return false;
	}
	std::cout << "已保存 PCD 文件: " << pcd_path << ",包含 " << cloud->points.size() << " 个点。" <<std::endl;
	return true;
}
int main()
{
// depth图像目录和固定输出 PCD 目录
std::string image_dir = "F:/Data/depth/";      //深度图数据路径
std::string pcd_dir = "F:/Data/pcd12/";     // 输出的pcdl文件路径示例
int index = 0 ;
// 创建固定输出目录(不检查是否存在)
CreateDirectorySimple(pcd_dir);

// 查找所有 PNG 深度图
std::vector<std::string> depth_images = FindAllPngDepthImages(image_dir);
std::cout << "找到 " << depth_images.size() << " 个 PNG 深度图。" << std::endl;

// 处理每个深度图
for (const auto& depth_path : depth_images) 
{
	index = index + 1;
	std::cout << "已经处理了: " << index << std::endl;
	//if (index % 2 != 1)
		//continue;
	// 提取文件名(不含路径)
	size_t pos = depth_path.find_last_of("/\\");
	std::string filename = (pos == std::string::npos) ? depth_path : depth_path.substr(pos + 1);

	// 提取基名(去除扩展名)
	size_t dot = filename.find_last_of('.');
	std::string base = (dot == std::string::npos) ? filename : filename.substr(0, dot);

	// 定义 PCD 文件路径
	std::string pcd_path = pcd_dir + base + ".pcd";
	
	// 处理并保存 PCD
	bool success = ProcessDepthImage(depth_path, pcd_path);
	if (!success) {
		std::cerr << "处理深度图失败: " << depth_path << std::endl;
	}
  }
  return 0;
}

(2)为什么用pcl写点云数据到pcd文件后用记事本打开乱码
如果写入pcd 的数据是按照ASCII码写的,其一定可以用文本文件打开,如果用二进制类型写的打开就是乱码。
上面的代码中的语句
1)if(pcl::io::savePCDFileASCII(pcd_path, *cloud) == -1)//以ASCII 码形式吸入pcd,写速度慢,文件大,但可以用文本文件查看点云坐标;
2)if (pcl::io::savePCDFileBinary(pcd_path, *cloud) == -1)//以二进制形式写入pcd,写速度快,文件小。

好了,先这样吧,pcl 博大精深,后面继续~

【PCL自学:Range Images】深度图与点云数据的转换及其应用(持续更新) PCL 深度图一、什么是深度图二、点云转深度图 PointCloud->Range Image三、利用深度提提取点云边缘 一、什么是深度图   目前深度图像的获取方法有激光雷达深度成像法、计算机立体视觉成像、坐标测量机法、莫尔条纹法、结构光法等等,针对深度图像的研究重点主要集中在以下几个方面,深度图像的分割技术 ,深度图像的边缘检测技术 ,基于不同视点的多幅深度图像的配准技术,基于深度数据的三维重建技术,基于三维深度图像的三维目标识别技术,深度图像的多分辨率建模和几何压缩技术等等,在PCL 中深度图像 阅读详情

相关推荐

点云PCL库学习-RGBD图像转化为点云PCD并显示

本文基于TUM数据集中一对时间戳最近的彩色图和深度图,通过相机模型转换和像素匹配生成了一帧点云数据。

weixin_41957687的博客 7106

深度图转点云

不想看废话的直接去最后复制代码🧐。

2023年才睡醒的双非研究生 4761

常见点云文件解析

最后一行是结束标志。我们在做2D视觉时,处理的就是类似一系列类似的二维数组,数组以图片的形式进行保存,处理的图片也有甚多的格式,比如png,jpg,bmp等。那我们在做3D视觉的时候,处理的主要是点云,点云就是由一些点的集合。一般由深度图还原的点云,有序点云按照图方阵一行一行的,从左上角到右下角排列,当然其中有一些无效点。有序点云在某些处理的时候还是很便利的,但是很多情况下是无法获取有序点云的。无序点云就是其中的点的集合,点排列之间没有任何顺序,点的顺序交换后没有任何影响,是比较普遍的点云形式。

YYY_77的博客 3090

【深度如何正确地转换为点云】

深度图和点云是两种存储3D测量结果的常见数据形式。深度图保存了场景中的点沿成像光轴Z向的距离分量,而点云图保存了XYZ三个方向的全部信息,两种直接存在一定的转换关系。本文介绍如何将深度图正确的转换为点云。

memmolo的博客 7118

深度图与点云互转:原理、实战与PCL/Open3D实现详解

在三维视觉与机器人感知领域,深度图像与三维点云是两种核心的数据表示形式。深度图像记录了场景中各点到相机的距离信息,而点云则由空间中的三维坐标点构成,直接表征物体的几何轮廓。理解两者间的转换原理,关键在于掌握相机模型与坐标系变换。通过针孔相机模型与内参矩阵,可以将二维像素坐标与深度值反投影为三维点,实现从深度图生成点云;反之,通过正向投影与栅格化,可将三维点云渲染为深度图像。这一技术是三维重建、SLAM和机器人视觉引导等应用的基石,例如在RGB-D SLAM中,高效的帧间点云配准依赖于快速准确的深度图转换。本

weixin_33857679的博客 1193

深度图与点云双向转换:原理、PCL/OpenCV实现与工程实践

在三维视觉与机器人感知领域,深度图像和点云是描述三维空间信息的两种核心数据表示形式。深度图像以规则二维矩阵存储每个像素的深度值,与图像处理算法亲和;点云则由无序的三维空间点构成,直接表征几何结构。其相互转换的原理基于相机模型,通过内参矩阵实现像素坐标与三维空间坐标的数学映射。这一转换技术具有重要价值,它解决了不同传感器(如结构光相机与激光雷达)数据与处理算法(如二维CNN与三维点云库)之间的适配问题,是打通二维感知与三维理解的关键。在应用场景上,深度图转点云常用于三维建模、点云配准(如ICP流程)和高度测量

weixin_34204722的博客 464

使用PCL从点云生成深度图并可视化

/ 设置噪声水平// 最小探测距离// 边缘宽度在生成深度图时,我们需要模拟传感器的位姿(位置和方向),这是通过一个仿射变换矩阵sensorPose来实现的。定义了坐标系,通常使用相机坐标系。noiseLevel和minRange分别用来控制噪声水平和最小采集距离。本文介绍了如何使用PCL从点云生成深度图并进行可视化。通过调整角度分辨率、视角范围和传感器位置等参数,用户可以生成精确的深度图。PCL提供了强大的点云处理和可视化功能,使得处理和展示3D数据变得更加简单高效。

weixin_73414031的博客 1208

3D点云基础知识(一)-初始入门-知乎整理(一)

作者:Mr.苍雪 链接:https://zhuanlan.zhihu.com/p/344635951 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。https://zhuanlan.zhihu.com/p/344635951 3D图像描述 RGB-D 点云 何为点云? 点云的获取 点云的内容 点云的属性 点云目前的主要存储格式包括:pts、LAS、PCD、.xyz 和. pcap 等 相应基础算法库对不同格式的支持 三维点云有多种表示方法 相比于图像数

xiaoyaolangwj的博客 5万+

PCD点云数据格式介绍

它旨在提供一种高效、灵活的方式来存储和处理点云数据,广泛应用于​。PCD 格式广泛应用于需要处理​。​ 是一种专门用于存储​。​的文件格式 ​。

yuanpan的专栏 3344

OpenCV中实现点云生成PCD格式

点云是三维空间中的一组数据点,用于表示物体的表面形状或场景的几何信息。OpenCV是一个流行的计算机视觉库,提供了丰富的功能来处理和操作图像、视频和三维数据。总结起来,通过使用OpenCV的Reprojecto3D函数和PCL库,我们可以方便地从深度图中生成点云,并将其保存为PCD格式的文件。PCD是一种常见的点云数据文件格式,它使用简单的文本或二进制形式来存储点云数据。最后,我们使用Point Cloud Library(PCL)提供的函数,将点云数据保存为PCD格式的文件。

UtiExamples的博客 416

告别SD卡!手把手教你用NVMe硬盘盒给Jetson Orin Nano离线烧录Ubuntu系统

本文详细介绍了如何利用NVMe硬盘盒为Jetson Orin Nano离线烧录Ubuntu系统,替代传统SD卡方案。通过硬件选择、系统镜像准备到烧录命令的全流程解析,帮助开发者提升存储性能与系统稳定性,特别适合嵌入式开发场景。

weixin_30808693的博客 459

【点云学习笔记】 PCL点云入门学习笔记(更新中)

它会被解释为点云数据。

QIN_student的博客 971

WPF窗口定位技巧:从基础到高级的三种实现方法

本文详细解析WPF窗口定位的三种核心方法:屏幕居中(CenterScreen)、父窗口居中(CenterOwner)和手动定位(Manual)。通过对比其适用场景、实现代码与注意事项,帮助开发者根据实际需求选择最佳方案,从而提升WPF应用程序的用户体验与专业度。

weixin_29224309的博客 272

2:PCD文件格式

本章参考,介绍了PCD(点云数据)文件格式及其在点云库(PCL)中的使用方式。

m0_55868528的博客 817

算法面经手撕系列(2)--手撕BatchNormlization

手动实现/手撕BatchNormlization

罟霖同学的站点 865

【Unity3D】RTS Engine 笔记一

RTS Engine 中配置一个新场景, 初步认识GameManager、设置地形以及配置地形网格搜索

ViYeye的博客 1650

[PCL教程] PCL漫游之I/O, KeyPoints,Range Image

目录4 输入输出 I/O4.1 PCD文件格式4.1.1 PCD版本4.1.2 文件头header4.1.3 数据存储类型4.1.4 PCD文件的优势4.2 从PCD文件中读取点云4.3 将点云写入PCD文件4.4 合并两个点云4.5 各种设备的接口 4 输入输出 I/O io库,读写点云数据,从各种传感器获取点云。 4.1 PCD文件格式 鉴于其他格式(ply, obj, stl, x3d等)存在一些问题,PCL主要使用PCD格式。当然也可以使用其他格式。 4.1.1 PCD版本 当前官方版本0.7 (P

Deephome的博客 540

深入解析:el-table合并单元格

  在企业级应用开发中,我们经常需要处理复杂的数据展示需求。在构建复杂的数据展示后台时,我们常常需要将表格中具有相同属性的行进行视觉上的合并,以提升信息的聚合度和可读性。在 Element Plus 的 el-table 组件中,span-method 属性是实现单元格合并的核心机制,允许开发者自定义单元格的合并逻辑,开发者可以通过实现自定义合并策略来满足各种负责需求。  合并行的本质是通过计算相邻行数据的相似性,确定满足合并的单元格范围,然后通过 DOM 操作将多个单元格合并为一个。这种操作在前端数据可视

独泪了无痕 229

彩色点云生成与PCD保存:从RGB-D到PCL实战指南

点云数据处理是三维视觉与机器人感知领域的基础环节,其核心价值在于将原始传感器数据转化为可计算、可存储的结构化三维信息。彩色点云在几何坐标之外附加了颜色属性,能够显著提升场景理解的直观性与后续算法的鲁棒性。在工程实践中,深度图与彩色图的像素级对齐,再结合相机内参矩阵进行反投影,是生成彩色点云的通用原理。点云库PCL提供了高效的数据结构与读写接口,而PCD文件格式因其灵活字段定义和与PCL生态的天然兼容,成为存储彩色点云的常见载体。此类技术广泛应用于室内重建、自动驾驶感知、增强现实等场景。从RGB-D相机、激光

weixin_32073537的博客 83

Solidworks在Windows 11上安装失败?这里有解决方案

通过上述步骤,你应该能够解决在Windows 11上安装Solidworks时遇到的问题。这个方法通过调整注册表的设置,提高了安装程序的权限,从而有效避免了安装过程中的权限障碍。当然,每个系统的具体情况可能有所不同,如果在尝试上述方法后仍然无法解决问题,建议联系Solidworks的技术支持团队,获取更专业的帮助。希望本文能够对你有所帮助,祝你工作顺利,设计无忧!

nntxthml的博客 4912

k8s 查看cpu使用率最高的pod

在 Kubernetes 中,可以使用命令查看 Pod 的资源使用情况,从而找到 CPU 使用率最高的 Pod。

u010674101的专栏 3345

一文看懂PCD文件格式

在使用PCL(Point Cloud Library)处理点云数据时,你一定会遇到 .pcd 文件。它是PCL专用的点云数据格式,结构清晰、功能强大。本文用一个实际例子,带你快速理解PCD文件的每一行含义。掌握这些基础知识,你就能轻松读写点云数据,为后续的滤波、配准、分割等操作打好基础!

m0_37603703的博客 686

海康VisionMaster全局通信实战:从数据接收到流程触发

本文详细解析了海康VisionMaster全局通信的实战应用,重点阐述了如何通过配置通信模块与编写全局脚本,实现从外部设备(如PLC)接收数据并触发内部视觉流程。文章以TCP/IP通信为例,深入讲解了数据接收、解析、全局变量设置及流程触发的核心代码与调试技巧,帮助用户打通自动化项目中的设备联动关键环节。

weixin_29295541的博客 569

常见点云文件解析学习笔记

本文主要介绍了一些常见的点云文件的格式以及相关的3D处理开源算法库。目的主要是为了了解这些格式,加深对点云组成的理解,以及方便日后读取文件时进行查看。

技术菜鸟的博客 4242

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

彩色图像和深度图像合成点云

彩色图像 深度图像 点云图 从2D到3D(数学部分) 上面两个图像给出了机器人外部世界的一个局部的信息. 假设这个世界由一个点云来描述:X={x1,…,xn}.其中每一个点,有r,g,b,x,y,z一共6个分量,表示它们颜色与空间位置。 颜色方面,主要由彩色图像记录; 而空间位置,可以由图像和相机模型、姿态一起计算出来。 对于常规相机,SLAM里使用针孔相机模型: ...

qq_43176116的博客 8487

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

3D点云基础知识

3D点云 基础知识,包括属性、表示方法、文件格式、常用库等

多敲代码! 4171

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

上一篇: 学习MRI处理过程中搜到的宝藏网站
下一篇: 记录搜罗到的Matlab 对散点进行椭圆拟合
发光的小豆芽
博客等级 码龄12年 2802粉丝 72原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值