#include \n#include \n#include \n#include <pcl/io/ply_io.h>\n#include <pcl/point_types.h>\n#include <pcl/visualization/pcl_visualizer.h>\n#include <opencv2/opencv.hpp>\n#include <pcl/point_cloud.h>\n#include <pcl/point_types.h>\nvoid stemDiameter(std::vector<pcl::PointCloudpcl::PointXYZRGB::Ptr>& inputPointClouds) {\n\t// 导入点云文件\n\tpcl::PointCloudpcl::PointXYZRGB::Ptr cloud(new pcl::PointCloudpcl::PointXYZRGB);\n\tpcl::io::loadPLYFilepcl::PointXYZRGB("D:\DIANYUNWENJIANJIA\test_ply.ply", *cloud);\n\n\t// 提取索引号为43的点的y值\n\tfloat y = cloud->points[4].y;\n\n\t// 将筛选后的切片点云存储在vector中\n\tstd::vector<pcl::PointCloudpcl::PointXYZRGB::Ptr> slicedPointClouds;\n\tstd::vector<pcl::PointCloudpcl::PointXYZRGB::Ptr> projectedPointClouds;\n\n\t// 切片的厚度范围\n\tfloat minThickness = 0.02;\n\tfloat maxThickness = 0.1;\n\tint numSlices = 8;\n\tfloat thicknessStep = (maxThickness - minThickness) / numSlices;\n\n\t// 创建每个切片的点云\n\tfor (int i = 0; i < numSlices; ++i) {\n\t float sliceMin = y + (i * thicknessStep);\n\t float sliceMax = y + ((i + 1) * thicknessStep);\n\n\t pcl::PointCloudpcl::PointXYZRGB::Ptr filteredCloud(new pcl::PointCloudpcl::PointXYZRGB);\n\t for (size_t j = 0; j < cloud->points.size(); ++j) {\n\t if (cloud->points[j].y > sliceMin && cloud->points[j].y < sliceMax) {\n\t filteredCloud->points.push_back(cloud->points[j]);\n\t }\n\t }\n\t filteredCloud->width = filteredCloud->points.size();\n\t filteredCloud->height = 1;\n\n\t // 将切片点云投影到 XZ 平面\n\t pcl::PointCloudpcl::PointXYZRGB::Ptr projectedCloud(new pcl::PointCloudpcl::PointXYZRGB);\n\t for (size_t j = 0; j < filteredCloud->points.size(); ++j) {\n\t pcl::PointXYZRGB point;\n\t point.x = filteredCloud->points[j].x;\n\t point.y = 0; // 投影到 XZ 平面,y值设为0\n\t point.z = filteredCloud->points[j].z;\n\t point.r = 0;\n\t point.g = 255;\n\t point.b = 0; // 投影颜色为绿色\n\n\t projectedCloud->points.push_back(point);\n\t }\n\t projectedCloud->width = projectedCloud->points.size();\n\t projectedCloud->height = 1;\n\n\t slicedPointClouds.push_back(filteredCloud);\n\t projectedPointClouds.push_back(projectedCloud); // 注意修改此处\n\n\t inputPointClouds.push_back(projectedPointClouds[i]); // 注意修改此处\n\t}\n\n\t// 创建PCL可视化对象\n\tpcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("PointCloud Viewer"));\n\n\t// 将原始点云显示为白色\n\tpcl::visualization::PointCloudColorHandlerRGBFieldpcl::PointXYZRGB white_color(cloud);\n\tviewer->addPointCloudpcl::PointXYZRGB(cloud, white_color, "original_cloud");\n\n\t// 将每个切片的点云显示为不同颜色\n\tstd::vector<pcl::visualization::PointCloudColorHandlerCustompcl::PointXYZRGB> colorHandlers;\n\tfor (int i = 0; i < numSlices; ++i) {\n\t int red = 255 * (i + 1) / numSlices;\n\t int green = 255 - (255 * (i + 1) / numSlices);\n\t int blue = 0;\n\t pcl::visualization::PointCloudColorHandlerCustompcl::PointXYZRGB colorHandler(slicedPointClouds[i], red, green, blue);\n\t colorHandlers.push_back(colorHandler);\n\t viewer->addPointCloudpcl::PointXYZRGB(slicedPointClouds[i], colorHandler, "filtered_cloud_" + std::to_string(i));\n\n\t pcl::visualization::PointCloudColorHandlerCustompcl::PointXYZRGB projectedColorHandler(projectedPointClouds[i], 0, 255, 0);\n\t viewer->addPointCloudpcl::PointXYZRGB(projectedPointClouds[i], projectedColorHandler, "projected_cloud_" + std::to_string(i));\n\t}\n\n\t// 设置点云可视化参数\n\tviewer->setBackgroundColor(0, 0, 0);\n\tviewer->initCameraParameters();\n\n\t// 开始可视化循环\n\twhile (!viewer->wasStopped()) {\n\t viewer->spinOnce();\n\t}\n\n\t// 保存每个切片的点云为PLY文件\n\tfor (int i = 0; i < numSlices; ++i) {\n\t pcl::io::savePLYFileBinary("D:\DIANYUNWENJIANJIA\茎直径切片_" + std::to_string(i) + "ply.ply", *slicedPointClouds[i]);\n\t pcl::io::savePLYFileBinary("D:\DIANYUNWENJIANJIA\茎直径切片" + std::to_string(i) + "_投影_ply.ply", *projectedPointClouds[i]);\n\t}\n}\n\nvoid fitEllipses(const std::vector<pcl::PointCloudpcl::PointXYZRGB::Ptr>& projectedPointClouds)\n{\n\tstd::cout << "椭圆拟合结果:" << std::endl;\n\n\tfor (size_t i = 0; i < projectedPointClouds.size(); ++i) {\n\t pcl::PointCloudpcl::PointXYZRGB::Ptr cloud = projectedPointClouds[i];\n\t size_t numPoints = cloud->points.size();\n\n\t // 检查点的数量是否满足椭圆拟合的最小要求\n\t if (numPoints < 6)\n\t {\n\t std::cout << "切片 " << i << "不满足椭圆拟合要求。" << std::endl;\n\t continue;\n\t }\n\n\t // 将pcl::PointCloud转换为cv::Mat\n\t cv::Mat image(numPoints, 2, CV_32FC1);\n\t for (size_t j = 0; j < numPoints; ++j) {\n\t image.at(j, 0) = cloud->points[j].x;\n\t image.at(j, 1) = cloud->points[j].z;\n\t }\n\n\t // 使用OpenCV进行椭圆拟合\n\t cv::RotatedRect ellipse = cv::fitEllipse(image);\n\n\t // 输出拟合椭圆的长轴长度\n\t std::cout << "切片 " << i << ":长轴长度 = " << std::max(ellipse.size.width, ellipse.size.height) << std::endl;\n\n\t // 可视化拟合的椭圆\n\t cv::Mat imageVis;\n\t cv::cvtColor(image, imageVis, cv::COLOR_BGR2RGB);\n\t cv::ellipse(imageVis, ellipse, cv::Scalar(0, 255, 0), 2);\n\t cv::imshow("拟合椭圆 (切片 " + std::to_string(i) + ")", imageVis);\n\t cv::waitKey(0);\n\t}\n}\n\nint main() {\n\tstd::vector<pcl::PointCloudpcl::PointXYZRGB::Ptr> inputPointClouds;\n\tstemDiameter(inputPointClouds);\n\n\tfitEllipses(inputPointClouds);\n\n\treturn 0;\n