PCL 1.15.1的common/io.h详细解析

一、文件概述

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

3D视觉算法开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值