1. 点云转深度图像,提取圆心;找到与圆心匹配的三维点;
2. 三维点以指定半径取邻域点,抽取所有邻域点的最大平面为参考平面;
3. 将平面附近点删去,得到凸台点。剩余凸台抽取最大平面,作为凸台顶面平面;
4. 将凸台点云变换到顶面平面作为xOy平面的坐标系下;
5. 对投影到顶面平面的2D点云识别边缘点,并拟合2D圆;找到圆心对应的原始点;
6. 圆心点到参考平面距离为凸台高度;
部分代码如下:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_src(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PLYReader reader;
//reader.setVerbosity(true); // 启用详细日志
if (reader.read(file_name, *cloud_src) == -1) {
pcl::console::print_error("Failed to load PLY file!\n");
return -1;
}
print_time("load data done");
#pragma omp parallel for
for (int tt = 0;tt < 100;tt++)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
*cloud = *cloud_src; // 逐字段深拷贝,包括点、宽、高、header 等
Eigen::Vector4f plane_coeff;
Eigen::Vector3f centroid;
if (!extractPlane(cloud, plane_coeff, centroid))
{
printf("Plane extract failed!\n");
continue;
}
erasePtsByDistToPlane(cloud, plane_coeff, 0.015);
//pcl::io::savePLYFileBinary(folder + "single" + ".ply", *cloud);
Eigen::Vector3f centroid2;
auto circle_plane = extractLargestPlane(cloud, centroid2);
Eigen::Vector4f plane2;
plane2[0] = circle_plane->values[0];
plane2[1] = circle_plane->values[1];
plane2[2] = circle_plane->values[2];
plane2[3] = circle_plane->values[3];
Coord2DTransformer transformer;
transformer.projectToPlane(cloud, plane2, centroid2);
//auprojectToPlane(cloud, circle_plane);
//pcl::io::savePLYFileBinary(folder + "circle_plane" + ".ply", *cloud2);
auto boundary = extractBoundaryPointsAlphaShape(transformer.points2d_cv, 0.01);
auto fitted_circle = fitCircleLeastSquares(boundary);
auto center = transformer.calcCoord3D(glm::dvec2(fitted_circle.center.x, fitted_circle.center.y));
auto height = pointToPlane(center, plane_coeff);// -(plane_coeff[0] * center.x + plane_coeff[1] * center.y + plane_coeff[3] * center.z) / plane_coeff[2];
//exportPointsToTXT(boundary, folder + "boundary.txt", 6);
printf("center = %.3f, %.3f, %.3f, radius = %.3f, height = %.3f\n",
center.x, center.y, center.z, fitted_circle.radius, height);
//auto cloud3 = extractBoundary(cloud2);
// pcl::io::savePLYFileBinary(folder + "boundary" + ".ply", *cloud3);
//Coord2DTransformer transformer;
//auto transformed_cloud = transformer.rectify(cloud, plane_coeff, centroid);
}