pcl::RANSAC 分割,获取云中的所有平面?

2023-11-25

我有一个点云库函数,可以检测点云中最大的平面。这很好用。现在,我想扩展此功能以分割云中的每个平面并将这些点复制到新的云中(例如,房间地板上有球体的场景将返回地板和墙壁,但不是球体,因为它不是平面的)。如何扩展下面的代码以获得所有飞机,而不仅仅是最大的飞机? (运行时间是这里的一个因素,所以我不想只是在循环中运行相同的代码,每次都删除新的最大平面)

int main(int argc, char** argv)
{
    pcl::visualization::CloudViewer viewer("viewer1");

    pcl::PCLPointCloud2::Ptr cloud_blob(new pcl::PCLPointCloud2), cloud_filtered_blob(new pcl::PCLPointCloud2);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>), cloud_p(new pcl::PointCloud<pcl::PointXYZ>), cloud_f(new pcl::PointCloud<pcl::PointXYZ>);

    // Fill in the cloud data
    pcl::PCDReader reader;
    reader.read("clouds/table.pcd", *cloud_blob);

    // Create the filtering object: downsample the dataset using a leaf size of 1cm
    pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
    sor.setInputCloud(cloud_blob);
    sor.setLeafSize(0.01f, 0.01f, 0.01f);
    sor.filter(*cloud_filtered_blob);

    // Convert to the templated PointCloud
    pcl::fromPCLPointCloud2(*cloud_filtered_blob, *cloud_filtered);

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

    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
    pcl::PointIndices::Ptr inliers(new pcl::PointIndices());
    // Create the segmentation object
    pcl::SACSegmentation<pcl::PointXYZ> seg;
    // Optional
    seg.setOptimizeCoefficients(true);
    seg.setModelType(pcl::SACMODEL_PLANE);
    seg.setMethodType(pcl::SAC_RANSAC);
    seg.setMaxIterations(1000);
    seg.setDistanceThreshold(0.01);

    // Create the filtering object
    pcl::ExtractIndices<pcl::PointXYZ> extract;

    int i = 0, nr_points = (int)cloud_filtered->points.size();
    // While 30% of the original cloud is still there
    while (cloud_filtered->points.size() > 0.3 * nr_points)
    {
        // Segment the largest planar component from the remaining cloud
        seg.setInputCloud(cloud_filtered);
        pcl::ScopeTime scopeTime("Test loop");
        {
            seg.segment(*inliers, *coefficients);
        }
        if (inliers->indices.size() == 0)
        {
            std::cerr << "Could not estimate a planar model for the given dataset." << std::endl;
            break;
        }

        // Extract the inliers
        extract.setInputCloud(cloud_filtered);
        extract.setIndices(inliers);
        extract.setNegative(false);
        extract.filter(*cloud_p);
        std::cerr << "PointCloud representing the planar component: " << cloud_p->width * cloud_p->height << " data points." << std::endl;

        }

    viewer.showCloud(cloud_p, "viewer1");
    while (!viewer.wasStopped()) {}

    return (0);
}

获得第一个平面后,删除这些点并使用算法计算新平面,直到估计平面不再有任何点为止。第二种情况是因为使用RANSAC只要有足够的点就总会找到一个平面。我在这里做了类似的事情(这是 ros 节点的回调):

void pointCloudCb(const sensor_msgs::PointCloud2::ConstPtr &msg){

    // Convert to pcl point cloud
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_msg (new pcl::PointCloud<pcl::PointXYZ>);
    pcl::fromROSMsg(*msg,*cloud_msg);
    ROS_DEBUG("%s: new ponitcloud (%i,%i)(%zu)",_name.c_str(),cloud_msg->width,cloud_msg->height,cloud_msg->size());

    // Filter cloud
    pcl::PassThrough<pcl::PointXYZ> pass;
    pass.setInputCloud(cloud_msg);
    pass.setFilterFieldName ("z");
    pass.setFilterLimits(0.001,10000);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
    pass.filter (*cloud);

    // Get segmentation ready
    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
    pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
    pcl::SACSegmentation<pcl::PointXYZ> seg;
    pcl::ExtractIndices<pcl::PointXYZ> extract;
    seg.setOptimizeCoefficients (true);
    seg.setModelType (pcl::SACMODEL_PLANE);
    seg.setMethodType (pcl::SAC_RANSAC);
    seg.setDistanceThreshold(_max_distance);

    // Create pointcloud to publish inliers
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_pub(new pcl::PointCloud<pcl::PointXYZRGB>);
    int original_size(cloud->height*cloud->width);
    int n_planes(0);
    while (cloud->height*cloud->width>original_size*_min_percentage/100){

        // Fit a plane
        seg.setInputCloud(cloud);
        seg.segment(*inliers, *coefficients);

        // Check result
        if (inliers->indices.size() == 0)
            break;

        // Iterate inliers
        double mean_error(0);
        double max_error(0);
        double min_error(100000);
        std::vector<double> err;
        for (int i=0;i<inliers->indices.size();i++){

            // Get Point
            pcl::PointXYZ pt = cloud->points[inliers->indices[i]];

            // Compute distance
            double d = point2planedistnace(pt,coefficients)*1000;// mm
            err.push_back(d);

            // Update statistics
            mean_error += d;
            if (d>max_error) max_error = d;
            if (d<min_error) min_error = d;

        }
        mean_error/=inliers->indices.size();

        // Compute Standard deviation
        ColorMap cm(min_error,max_error);
        double sigma(0);
        for (int i=0;i<inliers->indices.size();i++){

            sigma += pow(err[i] - mean_error,2);

            // Get Point
            pcl::PointXYZ pt = cloud->points[inliers->indices[i]];

            // Copy point to noew cloud
            pcl::PointXYZRGB pt_color;
            pt_color.x = pt.x;
            pt_color.y = pt.y;
            pt_color.z = pt.z;
            uint32_t rgb;
            if (_color_pc_with_error)
                rgb = cm.getColor(err[i]);
            else
                rgb = colors[n_planes].getColor();
            pt_color.rgb = *reinterpret_cast<float*>(&rgb);
            cloud_pub->points.push_back(pt_color);

        }
        sigma = sqrt(sigma/inliers->indices.size());

        // Extract inliers
        extract.setInputCloud(cloud);
        extract.setIndices(inliers);
        extract.setNegative(true);
        pcl::PointCloud<pcl::PointXYZ> cloudF;
        extract.filter(cloudF);
        cloud->swap(cloudF);

        // Display infor
        ROS_INFO("%s: fitted plane %i: %fx%s%fy%s%fz%s%f=0 (inliers: %zu/%i)",
                 _name.c_str(),n_planes,
                 coefficients->values[0],(coefficients->values[1]>=0?"+":""),
                 coefficients->values[1],(coefficients->values[2]>=0?"+":""),
                 coefficients->values[2],(coefficients->values[3]>=0?"+":""),
                 coefficients->values[3],
                 inliers->indices.size(),original_size);
        ROS_INFO("%s: mean error: %f(mm), standard deviation: %f (mm), max error: %f(mm)",_name.c_str(),mean_error,sigma,max_error);
        ROS_INFO("%s: poitns left in cloud %i",_name.c_str(),cloud->width*cloud->height);

        // Nest iteration
        n_planes++;
    }

    // Publish points
    sensor_msgs::PointCloud2 cloud_publish;
    pcl::toROSMsg(*cloud_pub,cloud_publish);
    cloud_publish.header = msg->header;
    _pub_inliers.publish(cloud_publish);
}

你可以找到整个节点here

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pcl::RANSAC 分割,获取云中的所有平面? 的相关文章

随机推荐

  • 从 angularjs 中的另一个指令内部添加指令

    从另一个指令中添加指令会使浏览器挂起 我想做的是 1 更改自定义元素指令 例如
  • GMSMapView animateToCameraPosition 放大-缩小动画

    我在 iOS Swift 和 Android 中使用 Google 地图服务 在android中 地图视图有一个方法叫做animatreCamera它有一个动画 其中运动具有 缩小 放大 效果 如果两个摄像机具有相同的变焦 则地图视图将缩小
  • python球物理模拟

    我看过 Peter Colling Ridge 的精彩教程 http www petercollingridge co uk pygame physical simulation 我正在扩展 PyParticles 脚本该代码可以在网站上获
  • 任务“:app:kaptGenerateStubsDebugKotlin”执行失败

    将 android studio 从 electricEel 更新为 Flamingo 插件后id kotlin kapt 导致错误 Execution failed for task app kaptGenerateStubsDebugK
  • 分配在堆上的对象

    每当创建任何新对象时 都会在堆上创建该对象 为每个对象分配的内存有两个附加字段 1 类型对象指针 2 同步块索引 这两个字段到底有什么用途 有人能解释一下吗 类型对象指针用于表示对象的类型 这是必需的 方法查找 vtable 检查石膏 寻找
  • HTML Purifier - 净化什么?

    我正在使用 HTML Purifier 来保护我的应用程序免受 XSS 攻击 目前 我正在净化所见即所得编辑器中的内容 因为这是唯一允许用户使用 XHTML 标记的地方 我的问题是 我是否应该在登录身份验证系统中的用户名和密码 或注册页面的
  • 在自定义编辑类型字段中添加多个输入元素

    有没有办法创建具有多个输入元素的自定义字段 我正在咨询文档创建单个输入元素非常简单 但我不太确定如何添加多个输入元素 以前有人走过这座桥吗 如果是这样 你是怎么做到的 这是一些示例代码 name Dimensions index Dimen
  • 在 BrowseFragment 中禁用行缩放/展开

    我还没有找到任何文档如何在将焦点从标题切换到 BrowseFragment 中的片段时禁用行缩放 倚背版本 24 2 0 BrowseFragment有一个功能enableMainFragmentScaling这部分解决了问题 图像现在具有
  • 如何查看是否点击同一个元素两次? jQuery

    如何检测用户是否点击同一个 div 我尝试过这个但没有成功 oldthis null var this this if oldthis this alert You clicked this last oldthis this 您无法比较
  • Laravel Auth::logout 未删除记住我的 cookie

    因此 我将会话的生命周期设置为两周 这样用户就不必多次登录或退出 然而今天我注意到一些事情 如果您注销 它会破坏您的会话 但会在您的浏览器上保留 记住我 cookie 这会导致问题 因为如果您在同一台计算机上切换帐户 8 10 次 您会收到
  • 事务中的 LAST_INSERT_ID() 可靠吗?

    我正在使用 mysql ado net C 这是我的问题 我知道 mysql 是并发的 但是我有文件数据 缩略图名称 和数据库数据 行 同步 如果我开始一笔交易 但因任何原因失败 这会是一个问题吗 如果我在两个核心上同时运行这段代码 它们会
  • 在iPhone App中如何检测设备的屏幕分辨率

    在 iPhone 应用程序中 在设备上运行App时如何检测运行App的设备的屏幕分辨率 CGRect screenBounds UIScreen mainScreen bounds 这将为您提供整个屏幕的分辨率 以点为单位 因此 iPhon
  • 异常处理模式

    这是我看到的一种常见模式 其中与异常相关的错误代码存储为静态最终整数 当创建要抛出的异常时 它是用这些代码之一以及错误消息构造的 这导致要捕获它的方法必须查看代码 然后决定操作过程 另一种选择似乎是为每个异常错误情况声明一个类 尽管相关异常
  • 在 Swing 应用程序中组织操作?

    我当前的应用程序有一个 JFrame 其中约有 15 个操作存储为 JFrame 中的字段 每个操作都是一个匿名类 其中一些非常长 将操作分解为它们自己的类 可能位于称为操作的子包中 是否很常见 如果不是 通常如何控制这种复杂性 Thank
  • 如何使用 mysql 二进制日志从删除数据库命令恢复?

    如何恢复使用 drop database 命令删除的 mysql 数据库 我可以访问二进制日志 这应该使这种类型的回滚成为可能 文档很糟糕 它暗示 DROP DATABASE 是可恢复的 但仅在我不熟悉的奇怪条件下http dev mysq
  • Flutter - 无线电动画未显示在 showDialog 上

    我正在尝试创建一个Radio in a showDialog 但是发生的动画Radio没有出现在showDialog 例如 当点击时foo2什么也没有发生 当你退出时showDialog然后回到它 foo2被选中 下面是代码和 gif 显示
  • C# 委托中的元帅 va_list

    我正在尝试用 c 来完成这项工作 C 标头 typedef void LogFunc const char format va list args bool Init uint32 version LogFunc log C 实现 stat
  • Java 同步和性能的一个方面

    我刚刚意识到我需要在某个方面同步大量数据收集代码 但性能是一个真正值得关注的问题 如果性能下降太多 我的工具就会被淘汰 我将分别写入 int 和 long 以及各种数组 ArrayList 和 Map 应用程序将有多个线程进行函数调用 这些
  • 如何使用 SASS 进行媒体查询?

    我已经通读了 SASS 文档 只能找到如何使用 scss 语法而不是 sass 语法进行媒体查询 sass 是具有严格的空白 没有大括号或分号的语法 如何使用 sass 语法进行媒体查询 media screen and min heigh
  • pcl::RANSAC 分割,获取云中的所有平面?

    我有一个点云库函数 可以检测点云中最大的平面 这很好用 现在 我想扩展此功能以分割云中的每个平面并将这些点复制到新的云中 例如 房间地板上有球体的场景将返回地板和墙壁 但不是球体 因为它不是平面的 如何扩展下面的代码以获得所有飞机 而不仅仅