Object 从点云创建遮罩(cv::Mat),从使用kinect观察的场景中提取对象

Object 从点云创建遮罩(cv::Mat),从使用kinect观察的场景中提取对象,object,opencv,image-recognition,image-segmentation,point-cloud-library,Object,Opencv,Image Recognition,Image Segmentation,Point Cloud Library,我正在尝试使用opencv实现一些对象识别。到目前为止,我只使用了记录的数据,没有任何令人不安的东西在场景中,这使我能够专注于识别部分与opencv。 现在我意识到,这通常不适用于真实场景。我想让我的算法适用于场景,在场景中,我将一个(单个)对象放在地板上或相机前面的桌子上,然后创建一个遮罩(cv::Mat),它允许我清空桌子/地板上的所有对象,但不包括主体 因此,我刚刚开始研究点云库。然而,我不知道该怎么做,也不知道最好的方法是什么。我想在Kinect相机的点云上使用平面分割算法,然后移除平面

我正在尝试使用opencv实现一些对象识别。到目前为止,我只使用了记录的数据,没有任何令人不安的东西在场景中,这使我能够专注于识别部分与opencv。 现在我意识到,这通常不适用于真实场景。我想让我的算法适用于场景,在场景中,我将一个(单个)对象放在地板上或相机前面的桌子上,然后创建一个遮罩(cv::Mat),它允许我清空桌子/地板上的所有对象,但不包括主体

因此,我刚刚开始研究点云库。然而,我不知道该怎么做,也不知道最好的方法是什么。我想在Kinect相机的点云上使用平面分割算法,然后移除平面,只留下对象的云。之后,我计划从角点(最外面的点)读取x和y坐标,以使用opencv创建遮罩对象。 这样行吗?是否有更好的想法或工作解决方案的来源/示例

谢谢你的帮助

。。。 问题是,分割后,点云不再有组织,我无法通过以下方式读取云中点的(预期)x,y坐标:

 for (size_t i = 0; i < (cloud)->points.size(); ++i)
              {
                 std::cout << "PointCloud x: " <<  cloud->points[i].x << std::endl;
                 std::cout << "PointCloud y: " <<  cloud->points[i].y  << std::endl;
                 std::cout << "PointCloud z: " <<  cloud->points[i].z  << std::endl;
              }
for(size_t i=0;i<(cloud)->points.size();++i)
{

std::cout假设您的对象识别算法是固定的,下面是一种典型的分割平面上方对象的方法。在您的情况下,我建议您在原始云中保留一组索引,以便您可以轻松地在最后创建遮罩;点云库通常提供此功能(或者,您可以忘记跟踪索引,一旦获得对象的最终点云,使用最近邻搜索来查找原始点云的索引-效率较低)

步骤如下:

  • 平面查找以查找并提取平面

  • 消除噪音:

  • 移除平面后在场景中查找对象的欧几里德聚类:

完成此操作后,您将获得分段对象中原始云点的索引集。请注意,原始云将被组织起来,以便很容易获得每个点的列/行。现在,您可以使用该索引创建遮罩,可能需要进行一些膨胀(侵蚀)以去除噪波

更多信息:

注意:如果您不必使用单独的分割和识别步骤,那么有许多算法可以同时执行这些操作,其中之一是LINEMOD,它位于PCL和OpenCV中


编辑 您曾写道,在查找原始组织点云的索引时需要帮助

我写道,有两种方法可以做到这一点——将每个步骤的输出作为点,搜索原始云以找到索引,或者只在每个步骤处理索引。第三种方法是利用已经实现的算法,让云组织起来(我不确定哪些算法提供了此选项).让我们来处理第二个选择

如果您看到上面使用的类的文档,pcl::SACSegmentation、pcl::StatisticaloutlierRemoving和pcl::EuclideanClusterExtraction,您将看到可以在输入上设置索引的工具。这类似于在OpenCV中设置掩码。这通常是对伴随.setInputCloud()的函数.setIndexes()的调用。类似地,如果您希望算法输出一组索引,而不是一个新的云,则可以传递一个要填充的Indexes对象(这是std::vector或pcl::PointIndexes,两者基本相同-请检查结构定义)

因此,如果您仅通过管道使用原始点云过程索引,您可以在末尾获得一组索引。要将这些索引转换为掩码,您可以从每个索引计算x和y值(据我记忆所及,有组织的点云在两个维度中压缩,行主要,因此这是整数除以宽度得到y,整数除以宽度得到x)


您在OpenCV中使用的对象识别算法是什么?您是否同意?这可能会决定您的分割方法。我从旋转对象(从各个侧面)提取SIFT特征这样,当我再次看到它时,我可以从任何视图中识别它。为了避免这种情况,我还存储了背景场景中的关键点,我想用opencv应用一个掩码。感谢您的逐步描述。我尝试按照您的建议做,但遇到了一些问题。我更新了我的问题。。。