不使用法线
#include
#include
#include
#include
void visualization(const pcl::PointCloud::Ptr cloud,
const pcl::ModelCoefficients::Ptr coefficients,
const pcl::PointIndices::Ptr inliers) {
boost::shared_ptr viewer(new pcl::visualization::PCLVisualizer("Plane"));
viewer->setBackgroundColor(0, 0, 0);
Eigen::Vector4f centroid;
pcl::compute3DCentroid(*cloud, centroid);
pcl::PointXYZ p1(centroid[0], centroid[1], centroid[2]);
pcl::PointXYZ p2(centroid[0] + coefficients->values[0],
centroid[1] + coefficients->values[1],
centroid[2] + coefficients->values[2]);
viewer->addArrow(p2, p1, 1, 0, 0, false);
viewer->addPointCloud(cloud, "cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud");
pcl::PointCloud::Ptr inlier_cloud(new pcl::PointCloud);
pcl::copyPointCloud(*cloud, *inliers, *inlier_cloud);
viewer->addPointCloud(inlier_cloud, "inlier_cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "inlier_cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "inlier_cloud");
while (!viewer->wasStopped()) {
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
}
void FittingPlane(const pcl::PointCloud::Ptr cloud,
pcl::ModelCoefficients::Ptr& coefficients,
pcl::PointIndices::Ptr& inliers) {
// Create the segmentation object
pcl::SACSegmentation seg;
// Optional
seg.setOptimizeCoefficients(true);
// Mandatory
seg.setModelType(pcl::SACMODEL_PLANE);
seg.setMethodType(pcl::SAC_RANSAC);
seg.setDistanceThreshold(0.03);
seg.setMaxIterations(1000);
seg.setInputCloud(cloud);
seg.segment(*inliers, *coefficients);
}
void FittingPlane(const pcl::PointCloud::Ptr cloud,
const Eigen::Vector3d& init_normal, const double& eps_angle_in_rad,
pcl::ModelCoefficients::Ptr& coefficients,
pcl::PointIndices::Ptr& inliers) {
pcl::SACSegmentation seg;
seg.setOptimizeCoefficients(true);
// seg.setModelType(pcl::SACMODEL_PLANE);
seg.setModelType(pcl::SACMODEL_PERPENDICULAR_PLANE);
seg.setMethodType(pcl::SAC_RANSAC);
seg.setDistanceThreshold(0.03);
seg.setMaxIterations(1000);
seg.setAxis(init_normal.cast());
seg.setEpsAngle(eps_angle_in_rad);
seg.setInputCloud(cloud);
seg.segment(*inliers, *coefficients);
}
int main(int argc, char**argv) {
// 加载点云模型
pcl::PointCloud::Ptr cloud(new pcl::PointCloud);
if (pcl::io::loadPCDFile("/tmp/color.pcd", *cloud) == -1) {
std::cerr << "can't load point cloud file" << std::endl;
return -1;
}
std::cout << "loaded " << cloud->width * cloud->height << " points" << std::endl;
std::cout << "field: " << pcl::getFieldsList(*cloud) << std::endl;
// 拟合平面
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
// FittingPlane(cloud, coefficients, inliers);
Eigen::Vector3d init_normal;
init_normal << 0, 0, 1;
double eps_angle_in_rad = 10 * M_PI / 180; // 估计的法线和初始法线相差10°以内
FittingPlane(cloud, init_normal, eps_angle_in_rad, coefficients, inliers);
std::cout << "Model coefficients: " << coefficients->values[0] << " "
<< coefficients->values[1] << " "
<< coefficients->values[2] << " "
<< coefficients->values[3];
// 点云渲染和可视化
visualization(cloud, coefficients, inliers);
return 0;
}
使用法线
#include
#include
#include
#include
#include
void EstimateNormal(const pcl::PointCloud::Ptr cloud,
pcl::PointCloud::Ptr normals) {
pcl::NormalEstimation normal_est;
normal_est.setInputCloud(cloud);
normal_est.setRadiusSearch(0.5); // 对于每一个点都用半径为5cm的近邻搜索方式
// normal_est.setKSearch(50); // 点云法向计算时,需要搜索的近邻点数目
pcl::search::KdTree::Ptr kdtree(new pcl::search::KdTree);
normal_est.setSearchMethod(kdtree); // 建立kdtree来进行近邻点集搜索
normal_est.compute(*normals);
}
void FittingPlane(const pcl::PointCloud::Ptr cloud,
const pcl::PointCloud::Ptr normals,
pcl::ModelCoefficients::Ptr& coefficients,
pcl::PointIndices::Ptr& inliers) {
pcl::SACSegmentationFromNormals seg;
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_PLANE);
seg.setMethodType(pcl::SAC_RANSAC);
seg.setNormalDistanceWeight(0.1); //设置表面法线权重系数
seg.setInputNormals(normals);
seg.setDistanceThreshold(0.03);
seg.setMaxIterations(1000);
seg.setInputCloud(cloud);
seg.segment(*inliers, *coefficients);
}
void visualization(const pcl::PointCloud::Ptr cloud,
const pcl::PointCloud::Ptr& normals,
const pcl::ModelCoefficients::Ptr coefficients,
const pcl::PointIndices::Ptr inliers) {
boost::shared_ptr viewer(new pcl::visualization::PCLVisualizer("Plane"));
viewer->setBackgroundColor(0, 0, 0);
Eigen::Vector4f centroid;
pcl::compute3DCentroid(*cloud, centroid);
// std::cout << "centroid2: " << centroid[0] << ", " << centroid[1] << ", " << centroid[2] << ", " << centroid[3] << std::endl;
pcl::PointXYZ p1(centroid[0], centroid[1], centroid[2]);
pcl::PointXYZ p2(centroid[0] + coefficients->values[0],
centroid[1] + coefficients->values[1],
centroid[2] + coefficients->values[2]);
viewer->addArrow(p2, p1, 1, 0, 0, false);
viewer->addPointCloud(cloud, "cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "cloud");
pcl::PointCloud::Ptr inlier_cloud(new pcl::PointCloud);
pcl::copyPointCloud(*cloud, *inliers, *inlier_cloud);
viewer->addPointCloud(inlier_cloud, "inlier_cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "inlier_cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "inlier_cloud");
viewer->addPointCloudNormals(cloud, normals, 5, 0.03, "normals");
while (!viewer->wasStopped()) {
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
}
int main(int argc, char**argv) {
// 加载点云模型
pcl::PointCloud::Ptr cloud(new pcl::PointCloud);
if (pcl::io::loadPCDFile("/tmp/color.pcd", *cloud) == -1) {
std::cerr << "can't load point cloud file" << std::endl;
return -1;
}
std::cout << "loaded " << cloud->width * cloud->height << " points" << std::endl;
std::cout << "field: " << pcl::getFieldsList(*cloud) << std::endl;
// 计算法线
pcl::PointCloud::Ptr normals(new pcl::PointCloud);
EstimateNormal(cloud, normals);
// 拟合平面
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
FittingPlane(cloud, normals, coefficients, inliers);
std::cout << "Model coefficients: " << coefficients->values[0] << " "
<< coefficients->values[1] << " "
<< coefficients->values[2] << " "
<< coefficients->values[3];
// 点云渲染和可视化
visualization(cloud, normals, coefficients, inliers);
return 0;
}