首页 > 其他分享 >点云学习笔记16——提取点云的边界,填充边界

点云学习笔记16——提取点云的边界,填充边界

时间:2024-11-12 21:18:16浏览次数:3  
标签:边界 16 points pcl 点云 boundary PointCloud id cloud

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

void BoundaryExtraction(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_boundary, int resolution)
{
	pcl::PointXYZ px_min = *std::min_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.x < pt2.x; });
	pcl::PointXYZ px_max = *std::max_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.x < pt2.x; });

	float delta_x = (px_max.x - px_min.x) / resolution;
	float min_y = INT_MAX, max_y = -INT_MAX;
	std::vector<int> indexs_x(2 * resolution + 2);
	std::vector<std::pair<float, float>> minmax_x(resolution + 1, { INT_MAX,-INT_MAX });
	for (size_t i = 0; i < cloud->size(); ++i)
	{
		int id = (cloud->points[i].x - px_min.x) / delta_x;
		if (cloud->points[i].y < minmax_x[id].first)
		{
			minmax_x[id].first = cloud->points[i].y;
			indexs_x[id] = i;
		}
		else if (cloud->points[i].y > minmax_x[id].second)
		{
			minmax_x[id].second = cloud->points[i].y;
			indexs_x[id + resolution + 1] = i;
		}
	}

	pcl::PointXYZ py_min = *std::min_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.y < pt2.y; });
	pcl::PointXYZ py_max = *std::max_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.y < pt2.y; });

	float delta_y = (py_max.y - py_min.y) / resolution;
	float min_x = INT_MAX, max_x = -INT_MAX;
	std::vector<int> indexs_y(2 * resolution + 2);
	std::vector<std::pair<float, float>> minmax_y(resolution + 1, { INT_MAX,-INT_MAX });
	for (size_t i = 0; i < cloud->size(); ++i)
	{
		int id = (cloud->points[i].y - py_min.y) / delta_y;
		if (cloud->points[i].x < minmax_y[id].first)
		{
			minmax_y[id].first = cloud->points[i].x;
			indexs_y[id] = i;
		}
		else if (cloud->points[i].x > minmax_y[id].second)
		{
			minmax_y[id].second = cloud->points[i].x;
			indexs_y[id + resolution + 1] = i;
		}
	}

	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xboundary(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::copyPointCloud(*cloud, indexs_x, *cloud_xboundary);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_yboundary(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::copyPointCloud(*cloud, indexs_y, *cloud_yboundary);
	*cloud_boundary = *cloud_xboundary + *cloud_yboundary;
}

int main(int argc, char* argv[])
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>) ;
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_boundary(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::io::loadPCDFile("F:\\19.pcd", *cloud);

	BoundaryExtraction(cloud, cloud_boundary, 200);
	pcl::io::savePCDFile("F:\\boundary1.pcd", *cloud_boundary);

	pcl::visualization::PCLVisualizer viewer("boundary");
    viewer.setBackgroundColor(0, 0, 0);//三个参数,分别代表红、绿、蓝颜色
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> target_color(cloud_boundary->makeShared(), 128, 128, 0);//类的实例 target_color,它用于自定义点云的颜色
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> result_color(cloud_boundary->makeShared(), 0, 255, 0);
    viewer.addPointCloud(cloud_boundary, result_color, "result_cloud");//用于

    while (!viewer.wasStopped())
    {
        viewer.spinOnce(100);
    }


	return EXIT_SUCCESS;
}

填充边界

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

// 边界提取函数
void BoundaryExtraction(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_boundary, int resolution) {
    pcl::PointXYZ px_min = *std::min_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.x < pt2.x; });
    pcl::PointXYZ px_max = *std::max_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.x < pt2.x; });

    float delta_x = (px_max.x - px_min.x) / resolution;
    std::vector<int> indexs_x(2 * resolution + 2);
    std::vector<std::pair<float, float>> minmax_x(resolution + 1, { INT_MAX, -INT_MAX });
    for (size_t i = 0; i < cloud->size(); ++i) {
        int id = (cloud->points[i].x - px_min.x) / delta_x;
        if (cloud->points[i].y < minmax_x[id].first) {
            minmax_x[id].first = cloud->points[i].y;
            indexs_x[id] = i;
        } else if (cloud->points[i].y > minmax_x[id].second) {
            minmax_x[id].second = cloud->points[i].y;
            indexs_x[id + resolution + 1] = i;
        }
    }

    pcl::PointXYZ py_min = *std::min_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.y < pt2.y; });
    pcl::PointXYZ py_max = *std::max_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.y < pt2.y; });

    float delta_y = (py_max.y - py_min.y) / resolution;
    std::vector<int> indexs_y(2 * resolution + 2);
    std::vector<std::pair<float, float>> minmax_y(resolution + 1, { INT_MAX, -INT_MAX });
    for (size_t i = 0; i < cloud->size(); ++i) {
        int id = (cloud->points[i].y - py_min.y) / delta_y;
        if (cloud->points[i].x < minmax_y[id].first) {
            minmax_y[id].first = cloud->points[i].x;
            indexs_y[id] = i;
        } else if (cloud->points[i].x > minmax_y[id].second) {
            minmax_y[id].second = cloud->points[i].x;
            indexs_y[id + resolution + 1] = i;
        }
    }

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xboundary(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::copyPointCloud(*cloud, indexs_x, *cloud_xboundary);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_yboundary(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::copyPointCloud(*cloud, indexs_y, *cloud_yboundary);
    *cloud_boundary = *cloud_xboundary + *cloud_yboundary;
}

// 边界点云填充函数
void FillBoundary(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_boundary, pcl::PointCloud<pcl::PointXYZ>::Ptr filled_boundary, float step) {
    for (size_t i = 0; i < cloud_boundary->size() - 1; ++i) {
        pcl::PointXYZ pt1 = cloud_boundary->points[i];
        pcl::PointXYZ pt2 = cloud_boundary->points[i + 1];
        filled_boundary->push_back(pt1);

        // 插值生成填充点
        int num_steps = std::ceil(std::sqrt(std::pow(pt2.x - pt1.x, 2) + std::pow(pt2.y - pt1.y, 2)) / step);
        for (int j = 1; j <= num_steps; ++j) {
            pcl::PointXYZ interpolated_pt;
            interpolated_pt.x = pt1.x + j * (pt2.x - pt1.x) / num_steps;
            interpolated_pt.y = pt1.y + j * (pt2.y - pt1.y) / num_steps;
            interpolated_pt.z = pt1.z + j * (pt2.z - pt1.z) / num_steps;
            filled_boundary->push_back(interpolated_pt);
        }
    }
    filled_boundary->push_back(cloud_boundary->back()); // 添加最后一个边界点
}

int main(int argc, char* argv[]) {
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_boundary(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr filled_boundary(new pcl::PointCloud<pcl::PointXYZ>);

    pcl::io::loadPCDFile("F:\\19.pcd", *cloud);
    BoundaryExtraction(cloud, cloud_boundary, 200);
    
    // 插值填充边界
    FillBoundary(cloud_boundary, filled_boundary, 0.01); // 0.01表示插值步长

    pcl::io::savePCDFile("F:\\boundary1_filled.pcd", *filled_boundary);
    std::cout << "边界点云已保存为 boundary1_filled.pcd" << std::endl;

    // 可视化边界
    pcl::visualization::PCLVisualizer viewer("boundary");
    viewer.setBackgroundColor(0, 0, 0);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> target_color(filled_boundary->makeShared(), 128, 128, 0);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> result_color(filled_boundary->makeShared(), 0, 255, 0);
    viewer.addPointCloud(filled_boundary, result_color, "result_cloud");

    while (!viewer.wasStopped()) {
        viewer.spinOnce(100);
    }

    return EXIT_SUCCESS;
}

ransac拟合边界直线

#include <iostream>
#include <algorithm>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/filters/extract_indices.h>

// 边界提取函数
void BoundaryExtraction(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_boundary, int resolution) {
    // (边界提取代码保持不变)
    pcl::PointXYZ px_min = *std::min_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) { return pt1.x < pt2.x; });
    pcl::PointXYZ px_max = *std::max_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) { return pt1.x < pt2.x; });

    float delta_x = (px_max.x - px_min.x) / resolution;
    std::vector<int> indexs_x(2 * resolution + 2);
    std::vector<std::pair<float, float>> minmax_x(resolution + 1, { INT_MAX,-INT_MAX });
    for (size_t i = 0; i < cloud->size(); ++i) {
        int id = (cloud->points[i].x - px_min.x) / delta_x;
        if (cloud->points[i].y < minmax_x[id].first) {
            minmax_x[id].first = cloud->points[i].y;
            indexs_x[id] = i;
        }
        else if (cloud->points[i].y > minmax_x[id].second) {
            minmax_x[id].second = cloud->points[i].y;
            indexs_x[id + resolution + 1] = i;
        }
    }

    pcl::PointXYZ py_min = *std::min_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) { return pt1.y < pt2.y; });
    pcl::PointXYZ py_max = *std::max_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) { return pt1.y < pt2.y; });

    float delta_y = (py_max.y - py_min.y) / resolution;
    std::vector<int> indexs_y(2 * resolution + 2);
    std::vector<std::pair<float, float>> minmax_y(resolution + 1, { INT_MAX,-INT_MAX });
    for (size_t i = 0; i < cloud->size(); ++i) {
        int id = (cloud->points[i].y - py_min.y) / delta_y;
        if (cloud->points[i].x < minmax_y[id].first) {
            minmax_y[id].first = cloud->points[i].x;
            indexs_y[id] = i;
        }
        else if (cloud->points[i].x > minmax_y[id].second) {
            minmax_y[id].second = cloud->points[i].x;
            indexs_y[id + resolution + 1] = i;
        }
    }

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xboundary(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::copyPointCloud(*cloud, indexs_x, *cloud_xboundary);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_yboundary(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::copyPointCloud(*cloud, indexs_y, *cloud_yboundary);
    *cloud_boundary = *cloud_xboundary + *cloud_yboundary;
}

// RANSAC 直线拟合函数
void FitBoundaryLines(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_boundary) {
    pcl::SACSegmentation<pcl::PointXYZ> seg;
    pcl::ExtractIndices<pcl::PointXYZ> extract;
    pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);

    seg.setOptimizeCoefficients(true);
    seg.setModelType(pcl::SACMODEL_LINE);
    seg.setMethodType(pcl::SAC_RANSAC);
    seg.setDistanceThreshold(0.01);

    pcl::PointCloud<pcl::PointXYZ>::Ptr remaining_points(new pcl::PointCloud<pcl::PointXYZ>(*cloud_boundary));

    int line_count = 0;
    while (remaining_points->size() > 10) {
        seg.setInputCloud(remaining_points);
        seg.segment(*inliers, *coefficients);

        if (inliers->indices.empty()) break;

        std::cout << "直线 " << ++line_count << " 系数: "
            << coefficients->values[0] << " " << coefficients->values[1] << " " << coefficients->values[2] << " "
            << coefficients->values[3] << " " << coefficients->values[4] << " " << coefficients->values[5] << std::endl;

        pcl::PointCloud<pcl::PointXYZ>::Ptr line_points(new pcl::PointCloud<pcl::PointXYZ>);
        extract.setInputCloud(remaining_points);
        extract.setIndices(inliers);
        extract.setNegative(false);
        extract.filter(*line_points);

        // 将已拟合的直线点从 remaining_points 中删除
        extract.setNegative(true);
        pcl::PointCloud<pcl::PointXYZ>::Ptr temp_points(new pcl::PointCloud<pcl::PointXYZ>);
        extract.filter(*temp_points);
        remaining_points.swap(temp_points);
    }
}

int main(int argc, char* argv[]) {
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_boundary(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::io::loadPCDFile("F:\\111.pcd", *cloud);

    BoundaryExtraction(cloud, cloud_boundary, 200);
    pcl::io::savePCDFile("F:\\boundary2.pcd", *cloud_boundary);

    // 使用 RANSAC 拟合直线
    FitBoundaryLines(cloud_boundary);

    // 可视化边界点云
    pcl::visualization::PCLVisualizer viewer("Boundary with Lines");
    viewer.setBackgroundColor(0, 0, 0);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color_handler(cloud_boundary, 0, 255, 0);
    viewer.addPointCloud(cloud_boundary, color_handler, "Boundary Points");

    while (!viewer.wasStopped()) {
        viewer.spinOnce(100);
    }

    return EXIT_SUCCESS;
}

标签:边界,16,points,pcl,点云,boundary,PointCloud,id,cloud
From: https://blog.csdn.net/qq_64095888/article/details/143700117

相关文章

  • 题解:[SCOI2016] 美味
    前置知识:可持久化线段树(主席树)洛谷3293[SCOI2016]美味问题有一个长度为\(n\)的序列\(a_1,a_2,...,a_n\)。每次询问给你\(b\)、\(x\),你需要求出\(\max\{a_i+x\bigoplusb\}\)。\(1\lel\ler\len\le2\times10^5,0\lea_i,b,x<10^5\)首先,有\(l,r\)应该......
  • 大数据新视界 -- 大数据大厂之 Impala 性能优化:优化数据加载的实战技巧(下)(16/30)
           ......
  • 2024.11.12 1632版
    起于《海奥华预言》的思考◆地球管理结构和参考持续更新中...... 英文地址:https://github.com/zhuyongzhe/Earth/tags中文地址:https://www.cnblogs.com/zhuyongzhe85作者:朱永哲 ---------------------------------------------------------------------------------......
  • 网络安全领域的 16 个专业,零基础入门到精通,收藏这一篇就够了_数字取证
    ......
  • 星源能投携手成都颐泰与英创力成功签署16MWh储能合作协议,助力智慧储能布局
    2024年11月,星源能投与成都颐泰携手,在四川英创力电子科技股份有限公司总部成功举行16MWh储能合作签约仪式。此次合作标志着星源能投与成都颐泰对西南地区储能需求的深入布局与支持。项目概况四川英创力电子科技股份有限公司成立于2011年,总部位于国家级遂宁经济技术开发区,是......
  • 洛谷P1618
    P1618三连击(升级版)-洛谷|计算机科学教育新生态三连击(升级版)题目描述将1,2,...9共9个数分成三组,分别组成三个三位数,且使这三个三位数的比例是A:B:C,试求出所有满足条件的三个三位数,若无解,输出`No!!!`。//感谢黄小U饮品完善题意输入格式三个数,A,B,C。输出格式......
  • 动态规划-背包问题——416.分割等和子集
    1.题目解析题目来源416.分割等和子集——力扣测试用例 2.算法原理1.状态表示这里背包问题基本上和母题的思路大相径庭,母题请见[模板]01.背包 ,这里的状态表示与装满背包的情况类似,第二个下标就是当选择的物品体积直接等于j时是否可以装入"背包",本题是求是否......
  • P1625求和 题解
    P1625求和题解题意求和题解比较好想,小学一年级奥数可以理解为高精度的大杂烩代码很简洁,可自行理解#include<bits/stdc++.h>//万能头#definelllonglong//开longlong usingnamespacestd;//命名空间lln,m,a[2005],b[2005],c[4000005];//a[0],b[0],c[0]......
  • warmup_csaw_2016
    题目链接:warmup_csaw_2016。下载附件后,使用IDA反编译,定位到main函数,如下。__int64__fastcallmain(inta1,char**a2,char**a3){chars[64];//[rsp+0h][rbp-80h]BYREFcharv5[64];//[rsp+40h][rbp-40h]BYREFwrite(1,"-WarmUp-\n",0xAuLL);writ......
  • AcWing 1626:链表元素分类 ← 单链表
    【题目来源】https://www.acwing.com/problem/content/1628/【题目描述】给定一个单链表,请编写程序将链表元素进行分类排列,使得所有负值元素都排在非负值元素的前面,而[0,K]区间内的元素都排在大于K的元素前面。但每一类内部元素的顺序是不能改变的。例如:给定链表为18→......