连接两个点云的字段或数据形成新点云

学习如何连接两个不同点云为一个点云,进行操作前要确保两个数据集中字段的类型相同和维度相等,同时了解如何连接两个不同点云的字段(例如颜色 法线)这种操作的强制约束条件是两个数据集中点的数目必须一样,例如:点云A是N个点XYZ点,点云B是N个点的RGB点,则连接两个字段形成点云C是N个点xyzrgb类型。

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>

int
main(int argc,char** argv)
{
if(argc!=2)
{
std::cerr<<"please specify command line arg '-f' or '-p'"<<std::endl;
exit(0);
}
pcl::PointCloud<pcl::PointXYZ> cloud_a,cloud_b,cloud_c;  
pcl::PointCloud<pcl::Normal> n_cloud_b;                  //存储进行连接时需要的normal点云
pcl::PointCloud<pcl::PointNormal> p_n_cloud_c;           //存储连接XYZ与normal后的点云
// 创建点云
cloud_a.width=5;
cloud_a.height=cloud_b.height=n_cloud_b.height=1;
cloud_a.points.resize(cloud_a.width*cloud_a.height);
if(strcmp(argv[1],"-p")==0)
{
cloud_b.width=3;
cloud_b.points.resize(cloud_b.width*cloud_b.height);
}
else{
n_cloud_b.width=5;
n_cloud_b.points.resize(n_cloud_b.width*n_cloud_b.height);
}
for(size_t i=0;i<cloud_a.points.size();++i)
{
cloud_a.points[i].x=1024*rand()/(RAND_MAX+1.0f);
cloud_a.points[i].y=1024*rand()/(RAND_MAX+1.0f);
cloud_a.points[i].z=1024*rand()/(RAND_MAX+1.0f);
}
if(strcmp(argv[1],"-p")==0)
for(size_t i=0;i<cloud_b.points.size();++i)
{
cloud_b.points[i].x=1024*rand()/(RAND_MAX+1.0f);
cloud_b.points[i].y=1024*rand()/(RAND_MAX+1.0f);
cloud_b.points[i].z=1024*rand()/(RAND_MAX+1.0f);
}
else
for(size_t i=0;i<n_cloud_b.points.size();++i)
{
n_cloud_b.points[i].normal[0]=1024*rand()/(RAND_MAX+1.0f);
n_cloud_b.points[i].normal[1]=1024*rand()/(RAND_MAX+1.0f);
n_cloud_b.points[i].normal[2]=1024*rand()/(RAND_MAX+1.0f);
}
std::cerr<<"Cloud A: "<<std::endl;
for(size_t i=0;i<cloud_a.points.size();++i)
std::cerr<<"    "<<cloud_a.points[i].x<<" "<<cloud_a.points[i].y<<" "<<cloud_a.points[i].z<<std::endl;

std::cerr<<"Cloud B: "<<std::endl;
if(strcmp(argv[1],"-p")==0)
for(size_t i=0;i<cloud_b.points.size();++i)
std::cerr<<"    "<<cloud_b.points[i].x<<" "<<cloud_b.points[i].y<<" "<<cloud_b.points[i].z<<std::endl;
else
for(size_t i=0;i<n_cloud_b.points.size();++i)
std::cerr<<"    "<<n_cloud_b.points[i].normal[0]<<" "<<n_cloud_b.points[i].normal[1]<<" "<<n_cloud_b.points[i].normal[2]<<std::endl;

//拷贝点云数据
if(strcmp(argv[1],"-p")==0)
{
cloud_c=cloud_a;
cloud_c+=cloud_b;
std::cerr<<"Cloud C: "<<std::endl;
for(size_t i=0;i<cloud_c.points.size();++i)
std::cerr<<"    "<<cloud_c.points[i].x<<" "<<cloud_c.points[i].y<<" "<<cloud_c.points[i].z<<" "<<std::endl;
}
else
{
pcl::concatenateFields(cloud_a,n_cloud_b,p_n_cloud_c);
std::cerr<<"Cloud C: "<<std::endl;
for(size_t i=0;i<p_n_cloud_c.points.size();++i)
std::cerr<<"    "<<
p_n_cloud_c.points[i].x<<" "<<p_n_cloud_c.points[i].y<<" "<<p_n_cloud_c.points[i].z<<" "<<
p_n_cloud_c.points[i].normal[0]<<" "<<p_n_cloud_c.points[i].normal[1]<<" "<<p_n_cloud_c.points[i].normal[2]<<std::endl;
}
return(0);
}

1.

if(argc!=2)
{
std::cerr<<"please specify command line arg '-f' or '-p'"<<std::endl;
exit(0);
}

这段代码就是判断你主函数参数是否都输入的;

2.

pcl::PointCloud<pcl::Normal> n_cloud_b;                  //存储进行连接时需要的normal点云
pcl::PointCloud<pcl::PointNormal> p_n_cloud_c;           //存储连接XYZ与normal后的点云

pcl::Normal是创建Normal类型的点(定点在样本曲面上的法线方向,以及对应的曲率测量值)访问的方式是 point[i].data_n[0]、point[i].normal[0]这种方式。(原因在于结构体的定义结构不一样)

pcl::PointNormal是存储XYZ数据的结构体,并且包括采样点的对应法线和曲率。

3.

if(strcmp(argv[1],"-p")==0)
{
cloud_b.width=3;
cloud_b.points.resize(cloud_b.width*cloud_b.height);
}
else{
n_cloud_b.width=5;
n_cloud_b.points.resize(n_cloud_b.width*n_cloud_b.height);
}

strcmp(argv[1],"-p")就是判断用户是否打-p 如果打-p 执行下面的程序

else{}//连接XYZ与normal则生成3个法线 

 

4.pcl::concatenateFields(cloud_a,n_cloud_b,p_n_cloud_c);就是完成连接点云(注意是竖着合并)

结果就不放了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
假设xyz点云文件格式为每行三个数字,分别是x、y、z坐标,以空格或制表符分隔。 首先,我们需要读入xyz点云文件,并把点云存储到一个vector中: ```cpp #include <iostream> #include <fstream> #include <vector> struct Point3D { float x, y, z; }; std::vector<Point3D> readPointCloud(const std::string& filename) { std::vector<Point3D> pointCloud; std::ifstream input(filename); if (!input.is_open()) { std::cerr << "Failed to open file: " << filename << std::endl; return pointCloud; } float x, y, z; while (input >> x >> y >> z) { pointCloud.push_back({x, y, z}); } input.close(); return pointCloud; } ``` 接下来,我们需要实现一个函数,将输入像素坐标形成矩形锚框,并根据锚框切割点云。假设输入的锚框信息为左上角坐标(x1, y1),右下角坐标(x2, y2),则可以按如下方式实现: ```cpp std::vector<Point3D> cropPointCloud(const std::vector<Point3D>& pointCloud, int x1, int y1, int x2, int y2) { // 确保锚框位置合法 if (x1 < 0 || y1 < 0 || x2 >= IMAGE_WIDTH || y2 >= IMAGE_HEIGHT || x1 > x2 || y1 > y2) { std::cerr << "Invalid anchor box: (" << x1 << ", " << y1 << ") - (" << x2 << ", " << y2 << ")" << std::endl; return pointCloud; } // 计算锚框对应的点云索引范围 size_t start = y1 * IMAGE_WIDTH + x1; size_t end = y2 * IMAGE_WIDTH + x2; // 切割点云 return std::vector<Point3D>(pointCloud.begin() + start, pointCloud.begin() + end + 1); } ``` 完整代码如下: ```cpp #include <iostream> #include <fstream> #include <vector> const int IMAGE_WIDTH = 640; const int IMAGE_HEIGHT = 480; struct Point3D { float x, y, z; }; std::vector<Point3D> readPointCloud(const std::string& filename) { std::vector<Point3D> pointCloud; std::ifstream input(filename); if (!input.is_open()) { std::cerr << "Failed to open file: " << filename << std::endl; return pointCloud; } float x, y, z; while (input >> x >> y >> z) { pointCloud.push_back({x, y, z}); } input.close(); return pointCloud; } std::vector<Point3D> cropPointCloud(const std::vector<Point3D>& pointCloud, int x1, int y1, int x2, int y2) { // 确保锚框位置合法 if (x1 < 0 || y1 < 0 || x2 >= IMAGE_WIDTH || y2 >= IMAGE_HEIGHT || x1 > x2 || y1 > y2) { std::cerr << "Invalid anchor box: (" << x1 << ", " << y1 << ") - (" << x2 << ", " << y2 << ")" << std::endl; return pointCloud; } // 计算锚框对应的点云索引范围 size_t start = y1 * IMAGE_WIDTH + x1; size_t end = y2 * IMAGE_WIDTH + x2; // 切割点云 return std::vector<Point3D>(pointCloud.begin() + start, pointCloud.begin() + end + 1); } int main() { std::vector<Point3D> pointCloud = readPointCloud("point_cloud.xyz"); std::vector<Point3D> croppedPointCloud = cropPointCloud(pointCloud, 100, 100, 200, 200); std::cout << "Original point cloud size: " << pointCloud.size() << std::endl; std::cout << "Cropped point cloud size: " << croppedPointCloud.size() << std::endl; return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值