SACSegmentation найти странную внутренность - PullRequest
0 голосов
/ 24 мая 2019

Когда я использую SACSegmentation, чтобы найти все перпендикулярные плоскости вектора нормали пола, я всегда получаю странные плоскости.Изображения показывают входное облако точек и результаты SACSegmentation. Original input point cloud.Correct ground plane.Wrong SACSegmentation inlier.

Я поиграл со значением setDistanceThreshold, и чем оно больше, тем больший странный внутренний сегмент у меня есть.Тем не менее, я всегда получаю неправильные самолеты.Я также попытался включить и выключить setOptimizeCoefficients, а также приблизить облако точек к началу координат.Я даже пытался использовать разные разумные ModelTypes и MethodTypes, такие как SACMODEL_NORMAL_PLANE и SACMODEL_NORMAL_PARALLEL_PLANE.Тем не менее, никто из них не решает проблему.Может ли кто-нибудь предоставить некоторые предложения?Заранее спасибо.

pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
    sor.setInputCloud (cloudPCL2);
    sor.setLeafSize (0.01, 0.01, 0.01);
    sor.filter (*cloudPCL2_result);

    pcl::fromPCLPointCloud2 (*cloudPCL2_result, *cloud_filtered);

    cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << endl;

    pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients());
    pcl::PointIndices::Ptr inliers (new pcl::PointIndices ());

    pcl::SACSegmentation<pcl::PointXYZRGB> seg;
    seg.setOptimizeCoefficients (true);

    seg.setModelType (pcl::SACMODEL_PERPENDICULAR_PLANE);
    seg.setMethodType (pcl::SAC_RANSAC);
    seg.setMaxIterations (2000);
    seg.setDistanceThreshold (0.07);
    seg.setAxis(normal);
    seg.setEpsAngle(pcl::deg2rad(20.0));

    int i = 0, nr_points = (int) cloud_filtered->points.size ();
    while (cloud_filtered->points.size () > 0.2 * nr_points) {
        seg.setInputCloud(cloud_filtered);
        seg.segment(*inliers, *coefficients);
        if (inliers->indices.size() == 0) {
            cerr << "Could not estimate a planar model for the given dataset." << endl;
            break;
        }

        extract.setInputCloud(cloud_filtered);
        extract.setIndices(inliers);
        extract.setNegative(false);
        extract.filter(*cloudOutput);

        stringstream ss;
        ss << "plane_" << i << ".pcd";
        writer.write<pcl::PointXYZRGB>(ss.str(), *cloudOutput, false);

        extract.setNegative(true);
        extract.filter(*cloudTmp);
        cerr << "PointCloud representing the planar component: " <<
cloudTmp->width * cloudTmp->height << " data points." << endl;
        cloud_filtered.swap(cloudTmp);
        i++;
    }

Я ожидаю, что SACSegmentation только найдет плоскость заземления и проигнорирует все точки на стене, но вместо этого я получил эти полосы стены вместе с правильной плоскостью заземления.

1 Ответ

0 голосов
/ 27 мая 2019

Из вашего кода + изображений я вижу, что первый RANSAC возвращает вам пол, а затем стену, параллельную полу.То, что вы хотите, это стена, которая перпендикулярна полу!Итак, самый быстрый способ получить это - снять параллельное ограничение и пойти с pcl::SACMODEL_PLANE после того, как вы получили свой первый результат в Ransac.Например,

...
while (...) {
    ...
    seg.segment(*inliers, *coefficients);
    // RESET THE RANSAC MODEL TYPE
    seg.setModelType (pcl::SACMODEL_PLANE);

Следуя исходному коду, вы сначала получите слово с вашим текущим ограничением по оси, а затем, сняв ограничение, сможете получить гораздо лучший результат.

...