一、文件概述
io.h 文件提供了一系列用于点云数据操作的实用函数,主要包括:
-
字段(field)查询和操作
-
点云拼接(concatenation)
-
点云复制和提取
-
数据类型转换
-
字节序交换
二、主要功能模块
1. 字段查询相关函数
1.1 getFieldIndex - 获取字段索引
函数签名:
inline int getFieldIndex(const pcl::PCLPointCloud2 &cloud, const std::string &field_name)
template <typename PointT> inline int
getFieldIndex(const std::string &field_name, std::vector<pcl::PCLPointField> &fields)
作用: 在点云中查找指定名称的字段,返回其索引位置。
参数:
-
cloud: 点云消息对象 -
field_name: 要查找的字段名称(如"x", "y", "z", "rgb"等) -
fields: PCLPointField向量
返回值: 字段索引(从0开始),如果未找到返回-1
使用示例:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
int main()
{
pcl::PCLPointCloud2 cloud;
// 假设cloud已经被填充数据
// 查找"x"字段的索引
int x_idx = pcl::getFieldIndex(cloud, "x");
if (x_idx != -1) {
std::cout << "找到x字段,索引为: " << x_idx << std::endl;
}
// 查找"intensity"字段
int intensity_idx = pcl::getFieldIndex(cloud, "intensity");
if (intensity_idx == -1) {
std::cout << "未找到intensity字段" << std::endl;
}
return 0;
}
1.2 getFields - 获取字段列表
函数签名:
template <typename PointT> inline std::vector<pcl::PCLPointField>
getFields()
作用: 获取特定点类型的所有字段信息。
使用示例:
#include <pcl/point_types.h>
#include <pcl/common/io.h>
int main()
{
// 获取PointXYZ类型的所有字段
std::vector<pcl::PCLPointField> fields = pcl::getFields<pcl::PointXYZ>();
std::cout << "PointXYZ包含 " << fields.size() << " 个字段:" << std::endl;
for (const auto& field : fields) {
std::cout << "- " << field.name
<< " (offset: " << field.offset
<< ", datatype: " << static_cast<int>(field.datatype)
<< ")" << std::endl;
}
return 0;
}
1.3 getFieldsList - 获取字段名称列表
函数签名:
inline std::string getFieldsList(const pcl::PCLPointCloud2 &cloud)
template <typename PointT> inline std::string
getFieldsList(const pcl::PointCloud<PointT> &cloud)
作用: 返回点云所有字段名称,以空格分隔的字符串形式。
使用示例:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
int main()
{
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
// 获取字段列表
std::string fields_list = pcl::getFieldsList(*cloud);
std::cout << "点云字段: " << fields_list << std::endl;
// 输出类似: "x y z rgb"
return 0;
}
2. 字段类型和大小相关函数
2.1 getFieldSize - 获取字段大小
函数签名:
inline int getFieldSize(const int datatype)
作用: 根据数据类型返回字段的字节大小。
参数:
-
datatype: PCLPointField中定义的数据类型(如INT8, FLOAT32等)
返回值: 字节数
使用示例:
#include <pcl/PCLPointField.h>
#include <pcl/common/io.h>
int main()
{
int size_float32 = pcl::getFieldSize(pcl::PCLPointField::FLOAT32);
std::cout << "FLOAT32 大小: " << size_float32 << " 字节" << std::endl; // 输出: 4
int size_uint8 = pcl::getFieldSize(pcl::PCLPointField::UINT8);
std::cout << "UINT8 大小: " << size_uint8 << " 字节" << std::endl; // 输出: 1
int size_float64 = pcl::getFieldSize(pcl::PCLPointField::FLOAT64);
std::cout << "FLOAT64 大小: " << size_float64 << " 字节" << std::endl; // 输出: 8
return 0;
}
2.2 getFieldType - 类型转换
函数签名:
inline int getFieldType(const int size, char type)
inline char getFieldType(const int type)
作用:
-
第一个函数:根据大小和类型字符返回PCLPointField类型
-
第二个函数:将PCLPointField类型转换为字符表示
参数:
-
size: 字节大小 -
type: 类型字符('B'=bool, 'F'=float, 'I'=signed int, 'U'=unsigned int)
使用示例:
#include <pcl/PCLPointField.h>
#include <pcl/common/io.h>
int main()
{
// 从大小和类型字符获取PCLPointField类型
int field_type = pcl::getFieldType(4, 'F');
std::cout << "4字节浮点类型: " << field_type << std::endl;
// 输出: 7 (对应FLOAT32)
// 从PCLPointField类型获取字符表示
char type_char = pcl::getFieldType(pcl::PCLPointField::FLOAT32);
std::cout << "FLOAT32的字符表示: " << type_char << std::endl;
// 输出: F
type_char = pcl::getFieldType(pcl::PCLPointField::INT32);
std::cout << "INT32的字符表示: " << type_char << std::endl;
// 输出: I
return 0;
}
3. 点云拼接函数
3.1 concatenate - 点云拼接
函数签名:
template <typename PointT>
bool concatenate(const pcl::PointCloud<PointT> &cloud1,
const pcl::PointCloud<PointT> &cloud2,
pcl::PointCloud<PointT> &cloud_out)
bool concatenate(const pcl::PCLPointCloud2 &cloud1,
const pcl::PCLPointCloud2 &cloud2,
pcl::PCLPointCloud2 &cloud_out)
bool concatenate(const pcl::PolygonMesh &mesh1,
const pcl::PolygonMesh &mesh2,
pcl::PolygonMesh &mesh_out)
作用: 将两个点云在点的维度上拼接(追加点)。
使用示例:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
int main()
{
// 创建两个点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud2(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out(new pcl::PointCloud<pcl::PointXYZ>);
// 填充cloud1
cloud1->width = 3;
cloud1->height = 1;
cloud1->points.resize(3);
for (size_t i = 0; i < cloud1->points.size(); ++i) {
cloud1->points[i].x = i * 0.1f;
cloud1->points[i].y = i * 0.2f;
cloud1->points[i].z = i * 0.3f;
}
// 填充cloud2
cloud2->width = 2;
cloud2->height = 1;
cloud2->points.resize(2);
for (size_t i = 0; i < cloud2->points.size(); ++i) {
cloud2->points[i].x = (i + 10) * 0.1f;
cloud2->points[i].y = (i + 10) * 0.2f;
cloud2->points[i].z = (i + 10) * 0.3f;
}
// 拼接
bool success = pcl::concatenate(*cloud1, *cloud2, *cloud_out);
if (success) {
std::cout << "拼接成功!" << std::endl;
std::cout << "cloud1点数: " << cloud1->points.size() << std::endl;
std::cout << "cloud2点数: " << cloud2->points.size() << std::endl;
std::cout << "输出点云点数: " << cloud_out->points.size() << std::endl;
// 输出: 5 (3 + 2)
}
return 0;
}
三、点云复制和提取函数
3.2 copyPointCloud - 点云复制
这是io.h中最重要的函数之一,有多个重载版本,用于不同场景的点云数据复制。
3.2.1 完整复制
函数签名:
template <typename PointInT, typename PointOutT> void
copyPointCloud(const pcl::PointCloud<PointInT> &cloud_in,
pcl::PointCloud<PointOutT> &cloud_out)
作用: 将整个点云从一种类型复制到另一种类型(可以是相同类型)。
使用示例:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
int main()
{
// 示例1: 相同类型复制
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_src(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_dst(new pcl::PointCloud<pcl::PointXYZ>);
// 填充源点云
cloud_src->width = 5;
cloud_src->height = 1;
cloud_src->points.resize(5);
for (size_t i = 0; i < cloud_src->points.size(); ++i) {
cloud_src->points[i].x = static_cast<float>(i);
cloud_src->points[i].y = static_cast<float>(i) * 2.0f;
cloud_src->points[i].z = static_cast<float>(i) * 3.0f;
}
// 复制
pcl::copyPointCloud(*cloud_src, *cloud_dst);
std::cout << "复制了 " << cloud_dst->points.size() << " 个点" << std::endl;
// 示例2: 不同类型复制(PointXYZ -> PointXYZI)
pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_xyzi(new pcl::PointCloud<pcl::PointXYZI>);
pcl::copyPointCloud(*cloud_src, *cloud_xyzi);
// XYZ字段被复制,intensity字段为默认值
std::cout << "转换后的点云点数: " << cloud_xyzi->points.size() << std::endl;
std::cout << "第一个点的intensity (默认值): " << cloud_xyzi->points[0].intensity << std::endl;
return 0;
}
3.2.2 基于索引的复制
函数签名:
template <typename PointT, typename IndicesVectorAllocator = std::allocator<index_t>> void
copyPointCloud(const pcl::PointCloud<PointT> &cloud_in,
const IndicesAllocator<IndicesVectorAllocator> &indices,
pcl::PointCloud<PointT> &cloud_out)
作用: 根据索引向量提取点云的子集。
使用示例:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <vector>
int main()
{
// 创建源点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_src(new pcl::PointCloud<pcl::PointXYZ>);
cloud_src->width = 10;
cloud_src->height = 1;
cloud_src->points.resize(10);
for (size_t i = 0; i < cloud_src->points.size(); ++i) {
cloud_src->points[i].x = static_cast<float>(i);
cloud_src->points[i].y = static_cast<float>(i) * 2.0f;
cloud_src->points[i].z = static_cast<float>(i) * 3.0f;
}
// 创建索引向量 - 提取偶数索引的点
std::vector<int> indices;
for (int i = 0; i < 10; i += 2) {
indices.push_back(i);
}
// 基于索引复制
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
pcl::copyPointCloud(*cloud_src, indices, *cloud_filtered);
std::cout << "原始点云: " << cloud_src->points.size() << " 个点" << std::endl;
std::cout << "提取的点云: " << cloud_filtered->points.size() << " 个点" << std::endl;
// 验证提取的点
for (size_t i = 0; i < cloud_filtered->points.size(); ++i) {
std::cout << "点 " << i << ": ("
<< cloud_filtered->points[i].x << ", "
<< cloud_filtered->points[i].y << ", "
<< cloud_filtered->points[i].z << ")" << std::endl;
}
return 0;
}
3.2.3 使用PointIndices的复制
函数签名:
template <typename PointT> void
copyPointCloud(const pcl::PointCloud<PointT> &cloud_in,
const PointIndices &indices,
pcl::PointCloud<PointT> &cloud_out)
作用: 使用PCL的PointIndices结构提取点云子集。
使用示例:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <pcl/PointIndices.h>
int main()
{
// 创建源点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
cloud->width = 100;
cloud->height = 1;
cloud->points.resize(100);
for (size_t i = 0; i < cloud->points.size(); ++i) {
cloud->points[i].x = 1024.0f * rand() / (RAND_MAX + 1.0f);
cloud->points[i].y = 1024.0f * rand() / (RAND_MAX + 1.0f);
cloud->points[i].z = 1024.0f * rand() / (RAND_MAX + 1.0f);
}
// 创建PointIndices对象
pcl::PointIndices::Ptr inliers(new pcl::PointIndices());
// 假设我们要提取前50个点
for (int i = 0; i < 50; ++i) {
inliers->indices.push_back(i);
}
// 提取点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_extracted(new pcl::PointCloud<pcl::PointXYZ>);
pcl::copyPointCloud(*cloud, *inliers, *cloud_extracted);
std::cout << "提取了 " << cloud_extracted->points.size() << " 个点" << std::endl;
return 0;
}
3.2.4 多个PointIndices的复制
函数签名:
template <typename PointT> void
copyPointCloud(const pcl::PointCloud<PointT> &cloud_in,
const std::vector<pcl::PointIndices> &indices,
pcl::PointCloud<PointT> &cloud_out)
作用: 使用多个PointIndices结构提取点云(合并多个索引集)。
使用示例:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <pcl/PointIndices.h>
int main()
{
// 创建源点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
cloud->width = 100;
cloud->height = 1;
cloud->points.resize(100);
for (size_t i = 0; i < cloud->points.size(); ++i) {
cloud->points[i].x = static_cast<float>(i);
cloud->points[i].y = static_cast<float>(i);
cloud->points[i].z = static_cast<float>(i);
}
// 创建多个索引集
std::vector<pcl::PointIndices> indices_vector;
// 第一组:0-9
pcl::PointIndices indices1;
for (int i = 0; i < 10; ++i) {
indices1.indices.push_back(i);
}
indices_vector.push_back(indices1);
// 第二组:50-59
pcl::PointIndices indices2;
for (int i = 50; i < 60; ++i) {
indices2.indices.push_back(i);
}
indices_vector.push_back(indices2);
// 第三组:90-99
pcl::PointIndices indices3;
for (int i = 90; i < 100; ++i) {
indices3.indices.push_back(i);
}
indices_vector.push_back(indices3);
// 提取所有索引对应的点
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_extracted(new pcl::PointCloud<pcl::PointXYZ>);
pcl::copyPointCloud(*cloud, indices_vector, *cloud_extracted);
std::cout << "从3个索引集提取了 " << cloud_extracted->points.size() << " 个点" << std::endl;
// 输出: 30 (10 + 10 + 10)
return 0;
}
3.2.5 带边界插值的复制
函数签名:
template <typename PointT> void
copyPointCloud(const pcl::PointCloud<PointT> &cloud_in,
pcl::PointCloud<PointT> &cloud_out,
int top, int bottom, int left, int right,
pcl::InterpolationType border_type, const PointT& value)
作用: 将点云复制到更大的点云中,并对边界进行插值处理。这对于图像式组织的点云(有width和height)特别有用。
参数:
-
top, bottom, left, right: 在输出点云中的位置边界 -
border_type: 边界插值类型 -
value: 常量边界时使用的值
边界类型说明:
-
BORDER_CONSTANT: 使用常量值填充 -
BORDER_REPLICATE: 复制边缘值 -
BORDER_REFLECT: 镜像反射 -
BORDER_REFLECT_101: 镜像反射(不包含边界) -
BORDER_WRAP: 循环包裹 -
BORDER_TRANSPARENT: 保持原始值
使用示例:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
int main()
{
// 创建小的源点云 (organized)
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_small(new pcl::PointCloud<pcl::PointXYZ>);
cloud_small->width = 3;
cloud_small->height = 3;
cloud_small->is_dense = false;
cloud_small->points.resize(cloud_small->width * cloud_small->height);
// 填充数据
for (size_t i = 0; i < cloud_small->points.size(); ++i) {
cloud_small->points[i].x = static_cast<float>(i);
cloud_small->points[i].y = static_cast<float>(i) * 2.0f;
cloud_small->points[i].z = static_cast<float>(i) * 3.0f;
}
// 创建大的输出点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_large(new pcl::PointCloud<pcl::PointXYZ>);
// 边界值
pcl::PointXYZ border_value;
border_value.x = border_value.y = border_value.z = 0.0f;
// 复制并添加边界
// 在大点云中,小点云位于 top=1, bottom=1, left=1, right=1 的位置
pcl::copyPointCloud(*cloud_small, *cloud_large,
1, 1, 1, 1, // 上下左右各1个点的边界
pcl::BORDER_REPLICATE, border_value);
std::cout << "原始点云大小: " << cloud_small->width << "x" << cloud_small->height << std::endl;
std::cout << "带边界的点云大小: " << cloud_large->width << "x" << cloud_large->height << std::endl;
// 输出: 5x5 (3+1+1 x 3+1+1)
return 0;
}
四、字段拼接函数
4.1 concatenateFields - 字段拼接
函数签名:
template <typename PointIn1T, typename PointIn2T, typename PointOutT> void
concatenateFields(const pcl::PointCloud<PointIn1T> &cloud1_in,
const pcl::PointCloud<PointIn2T> &cloud2_in,
pcl::PointCloud<PointOutT> &cloud_out)
bool concatenateFields(const pcl::PCLPointCloud2 &cloud1_in,
const pcl::PCLPointCloud2 &cloud2_in,
pcl::PCLPointCloud2 &cloud_out)
作用: 将两个点云按字段维度拼接(而非点的维度)。这意味着两个点云必须有相同数量的点,但可以有不同的字段。
重要说明:
-
如果两个输入点云有重叠的字段,第二个点云的数据会覆盖第一个点云的数据
-
两个点云必须有相同数量的点
使用示例:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <pcl/PCLPointCloud2.h>
#include <pcl/conversions.h>
int main()
{
// 示例1: 合并XYZ和RGB信息
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xyz(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::RGB>::Ptr cloud_rgb(new pcl::PointCloud<pcl::RGB>);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_xyzrgb(new pcl::PointCloud<pcl::PointXYZRGB>);
// 填充XYZ点云
cloud_xyz->width = 5;
cloud_xyz->height = 1;
cloud_xyz->points.resize(5);
for (size_t i = 0; i < cloud_xyz->points.size(); ++i) {
cloud_xyz->points[i].x = static_cast<float>(i);
cloud_xyz->points[i].y = static_cast<float>(i) * 2.0f;
cloud_xyz->points[i].z = static_cast<float>(i) * 3.0f;
}
// 填充RGB点云(必须有相同数量的点)
cloud_rgb->width = 5;
cloud_rgb->height = 1;
cloud_rgb->points.resize(5);
for (size_t i = 0; i < cloud_rgb->points.size(); ++i) {
cloud_rgb->points[i].r = static_cast<uint8_t>(i * 50);
cloud_rgb->points[i].g = static_cast<uint8_t>(i * 30);
cloud_rgb->points[i].b = static_cast<uint8_t>(i * 20);
}
// 拼接字段
pcl::concatenateFields(*cloud_xyz, *cloud_rgb, *cloud_xyzrgb);
std::cout << "拼接后的点云包含 " << cloud_xyzrgb->points.size() << " 个点" << std::endl;
std::cout << "第一个点: ("
<< cloud_xyzrgb->points[0].x << ", "
<< cloud_xyzrgb->points[0].y << ", "
<< cloud_xyzrgb->points[0].z << ") RGB("
<< static_cast<int>(cloud_xyzrgb->points[0].r) << ", "
<< static_cast<int>(cloud_xyzrgb->points[0].g) << ", "
<< static_cast<int>(cloud_xyzrgb->points[0].b) << ")" << std::endl;
// 示例2: 使用PCLPointCloud2
pcl::PCLPointCloud2::Ptr cloud2_xyz(new pcl::PCLPointCloud2);
pcl::PCLPointCloud2::Ptr cloud2_normal(new pcl::PCLPointCloud2);
pcl::PCLPointCloud2::Ptr cloud2_out(new pcl::PCLPointCloud2);
// 转换为PCLPointCloud2格式
pcl::toPCLPointCloud2(*cloud_xyz, *cloud2_xyz);
// 拼接(这里简化示例,实际使用时需要准备法线数据)
// bool success = pcl::concatenateFields(*cloud2_xyz, *cloud2_normal, *cloud2_out);
return 0;
}
实际应用场景:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <pcl/features/normal_3d.h>
int main()
{
// 实际场景:为XYZ点云添加法线信息
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xyz(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);
// ... 假设cloud_xyz已填充数据
// ... 假设cloud_normals已计算完成(使用法线估计)
// 将XYZ和法线合并
pcl::concatenateFields(*cloud_xyz, *cloud_normals, *cloud_with_normals);
std::cout << "合并后的点云包含位置和法线信息" << std::endl;
return 0;
}
五、点云与Eigen矩阵转换
5.1 getPointCloudAsEigen - 点云转Eigen矩阵
函数签名:
bool getPointCloudAsEigen(const pcl::PCLPointCloud2 &in, Eigen::MatrixXf &out)
作用: 将PCLPointCloud2的XYZ坐标提取到Eigen矩阵中。每行代表一个点的[x, y, z, 0]。
使用示例:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <pcl/PCLPointCloud2.h>
#include <pcl/conversions.h>
#include <Eigen/Dense>
int main()
{
// 创建点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
cloud->width = 5;
cloud->height = 1;
cloud->points.resize(5);
for (size_t i = 0; i < cloud->points.size(); ++i) {
cloud->points[i].x = static_cast<float>(i);
cloud->points[i].y = static_cast<float>(i) * 2.0f;
cloud->points[i].z = static_cast<float>(i) * 3.0f;
}
// 转换为PCLPointCloud2
pcl::PCLPointCloud2::Ptr cloud2(new pcl::PCLPointCloud2);
pcl::toPCLPointCloud2(*cloud, *cloud2);
// 转换为Eigen矩阵
Eigen::MatrixXf matrix;
bool success = pcl::getPointCloudAsEigen(*cloud2, matrix);
if (success) {
std::cout << "转换成功!" << std::endl;
std::cout << "矩阵大小: " << matrix.rows() << "x" << matrix.cols() << std::endl;
std::cout << "矩阵内容:\n" << matrix << std::endl;
// 每行是 [x, y, z, 0]
std::cout << "\n第一个点: ["
<< matrix(0, 0) << ", "
<< matrix(0, 1) << ", "
<< matrix(0, 2) << ", "
<< matrix(0, 3) << "]" << std::endl;
}
return 0;
}
5.2 getEigenAsPointCloud - Eigen矩阵转点云
函数签名:
bool getEigenAsPointCloud(Eigen::MatrixXf &in, pcl::PCLPointCloud2 &out)
作用: 将Eigen矩阵转换回PCLPointCloud2格式。
注意: 输出的PCLPointCloud2必须已经设置好字段!
使用示例:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <pcl/PCLPointCloud2.h>
#include <Eigen/Dense>
int main()
{
// 创建Eigen矩阵
Eigen::MatrixXf matrix(5, 4);
for (int i = 0; i < 5; ++i) {
matrix(i, 0) = static_cast<float>(i); // x
matrix(i, 1) = static_cast<float>(i) * 2.0f; // y
matrix(i, 2) = static_cast<float>(i) * 3.0f; // z
matrix(i, 3) = 0.0f; // padding
}
// 创建输出点云并设置字段
pcl::PCLPointCloud2 cloud_out;
cloud_out.height = 1;
cloud_out.width = matrix.rows();
// 设置字段(关键步骤!)
cloud_out.fields.resize(3);
cloud_out.fields[0].name = "x";
cloud_out.fields[0].offset = 0;
cloud_out.fields[0].datatype = pcl::PCLPointField::FLOAT32;
cloud_out.fields[0].count = 1;
cloud_out.fields[1].name = "y";
cloud_out.fields[1].offset = 4;
cloud_out.fields[1].datatype = pcl::PCLPointField::FLOAT32;
cloud_out.fields[1].count = 1;
cloud_out.fields[2].name = "z";
cloud_out.fields[2].offset = 8;
cloud_out.fields[2].datatype = pcl::PCLPointField::FLOAT32;
cloud_out.fields[2].count = 1;
cloud_out.point_step = 16; // 4 floats * 4 bytes
cloud_out.row_step = cloud_out.point_step * cloud_out.width;
cloud_out.data.resize(cloud_out.row_step * cloud_out.height);
cloud_out.is_dense = true;
// 转换
bool success = pcl::getEigenAsPointCloud(matrix, cloud_out);
if (success) {
std::cout << "转换成功!点云包含 " << cloud_out.width << " 个点" << std::endl;
}
return 0;
}
六、字节序交换函数
6.1 swapByte - 字节序交换
函数签名:
namespace pcl::io {
template <std::size_t N> void swapByte(char* bytes)
template <typename T> void swapByte(T& value)
}
作用: 交换字节序,用于处理大端和小端字节序的转换。
使用示例:
#include <pcl/common/io.h>
#include <iostream>
#include <cstring>
int main()
{
// 示例1: 交换float的字节序
float value = 3.14159f;
std::cout << "原始值: " << value << std::endl;
// 显示原始字节
unsigned char* bytes = reinterpret_cast<unsigned char*>(&value);
std::cout << "原始字节: ";
for (size_t i = 0; i < sizeof(float); ++i) {
printf("%02X ", bytes[i]);
}
std::cout << std::endl;
// 交换字节序
pcl::io::swapByte(value);
bytes = reinterpret_cast<unsigned char*>(&value);
std::cout << "交换后字节: ";
for (size_t i = 0; i < sizeof(float); ++i) {
printf("%02X ", bytes[i]);
}
std::cout << std::endl;
// 示例2: 交换int64的字节序
int64_t large_value = 0x0123456789ABCDEF;
std::cout << "\n原始int64值: 0x" << std::hex << large_value << std::endl;
pcl::io::swapByte(large_value);
std::cout << "交换后int64值: 0x" << std::hex << large_value << std::endl;
return 0;
}
七、边界插值类型详解
7.1 InterpolationType 枚举
定义:
enum InterpolationType
{
BORDER_CONSTANT = 0, // 常量填充
BORDER_REPLICATE = 1, // 边缘复制
BORDER_REFLECT = 2, // 镜像反射
BORDER_WRAP = 3, // 循环包裹
BORDER_REFLECT_101 = 4, // 镜像反射(不含边界)持原值)
BORDER_DEFAULT = BORDER_REFLECT_101
};
各种插值类型说明:
// 假设原始数据为: abcdefgh
// 需要在左右各扩展若干像素
BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh
BORDER_REFLECT: fedcba|abcdefgh|h_101: gfedcb|abcdefgh|gfedcba
BORDER_WRAP: cdefgh|abcdefgh|abcdefg
BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii (i为指定常量)
BORDER_TRANSPARENT: mnopqr|abcdefgh|tuvwxyz (保持原有值)
7.2 interpolatePointIndex - 插值索引计算
函数签名:
int interpolatePointIndex(int p, int length, InterpolationType type)
作用: 根据插值类型计算正确的点索引。
参数:
-
p: 要插值的点索引(可能超出范围) -
length: 有效范围的长度 -
type: 插值类型
使用示例:
#include <pcl/common/io.h>
#include <iostream>
int main()
{
int length = 10; // 假设有效索引范围是 0-9
std::cout << "BORDER_REPLICATE模式:" << std::endl;
for (int i = -3; i < 13; ++i) {
int idx = pcl::interpolatePointIndex(i, length, pcl::BORDER_REPLICATE);
std::cout << "索引 " << i << " -> -3 -> 0, -2 -> 0, -1 -> 0, 0 -> 0, ..., 9 -> 9, 10 -> 9, 11 -> 9
std::cout << "\nBORDER_WRAP模式:" << std::endl;
for (int i = -3; i < 13; ++i) {
int idx = pcl::interpolatePointIndex(i, length, pcl::BORDER_WRAP);
std::cout << "索引 " << i << " -> " << idx << std::endl;
}
// -3 -> 7, -2 -> 8, -1 -> 9, 0 -> 0, ..., 9 -> 9, 10 -> 0, 11 -> 1
std::cout << "\nBORDER_REFLECT_101模式:" << std::endl;
for (int i = -3; i < 13; ++i) {
int idx = pcl::interpolatePointIndex(i, length, pcl::BORDER_REFLECT_101);
std::cout << "索引 " << i << " -> " << idx << std::endl;
}
return 0;
}
八、实用工具函数
8.1 isSamePointType - 点类型检查
函数签名:
template <typename Point noexcept
作用: 编译时检查两个点类型是否相同。
使用示例:
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <iostream>
int main()
{
// 检查点类型是否相同
bool same1 = pcl::isSamePointType<pcl::PointXYZ, pcl::PointXYZ>();
std::cout << "PointXYZ vs PointXYZ: " << (same1 ? "相同" : "不同") << std::endl;
// 输出: 相同
bool same2 = pcl::isSamePointType<pcl::PointXYZ, pcl::PointXYZI>();
std::cout << "PointXYZ vs PointXYZI: " << (same2 ? "相同" : "不同") << std::endl;
// 输出: 不同
bool same3 = pcl::isSamePointType<pcl::PointXYZRGB, pcl::PointXYZRGBA>();
std::cout << "PointXYZRGB vs PointXYZRGBA: " << (same3 ? "相同" : "不同") << std::endl;
// 输出: 不同
// 在模板函数中使用
if constexpr (pcl::isSamePointType<pcl::PointXYZ, pcl::PointXYZ>()) {
std::cout << "类型相同,可以直接复制" << std::endl;
}
return 0;
}
8.2 getFieldsSizes - 获取字段大小列表
函数签名:
void getFieldsSizes(const std::vector<pcl::PCLPointField> &fields,
std::vector<int> &field_sizes)
作用: 获取所有有效字段(非"_"字段)的字节大小。
使用示例:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <pcl/PCLPointCloud2.h>
#include <pcl/conversions.h>
int main()
{
// 创建点云
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
// 获取字段
std::vector<pcl::PCLPointField> fields = pcl::getFields<pcl::PointXYZRGB>();
// 获取字段大小
std::vector<int> field_sizes;
pcl::getFieldsSizes(fields, field_sizes);
std::cout << "PointXYZRGB字段信息:" << std::endl;
for (size_t i = 0; i < fields.size(); ++i) {
if (fields[i].name != "_") { // 跳过填充字段
std::cout << "字段 " << fields[i].name
<< ": " << field_sizes[i] << " 字节" << std::endl;
}
}
return 0;
}


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



