【问题标题】:How to project point cloud onto the ground plane and transfer it into an 2D image (OpenCV Mat) in Point Cloud Library?如何将点云投影到地平面上并将其转换为点云库中的二维图像(OpenCV Mat)?
【发布时间】:2015-07-01 20:49:25
【问题描述】:

我想像这样分割地面上的石头并计算石头的面积:

我写了2年的OpenCV,发现仅使用OpenCV RGB图片很难分割石头,所以我使用kinect fusion扫描地面并得到一个点云,其中石头高于地面。
我使用点云库来分割地平面(绿色),如下所示:

现在我正在尝试将其余点投影到地平面上并获得 OpenCV Mat 格式的 2D 图像(原始点的高度成为地面 2D 图像中投影点的值),结果是是一张灰色的垫子图片。但这对我来说非常困难,您能给我一些建议吗?

如果我成功得到我的新灰色垫子,那么我可以对它进行分割,这对我来说很容易。

顺便问一下,有没有可以查看点的 (x,y,z) 坐标的点云查看器?

这是我的主要代码:

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);

pcl::io::loadPLYFile ("MeshedReconstruction.ply", *cloud);

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

seg.setInputCloud (cloud);
seg.segment (*inliers_groud, *coefficients);

if (inliers_groud->indices.size () == 0)
{
    PCL_ERROR ("Could not estimate a planar model for the given dataset.");
    return (-1);
}

std::cerr << "Model coefficients: " << coefficients->values[0] << " " 
    << coefficients->values[1] << " "
    << coefficients->values[2] << " " 
    << coefficients->values[3] << std::endl;

std::cerr << "Model inliers_groud: " << inliers_groud->indices.size () << std::endl;

// Create the filtering object
pcl::ExtractIndices<pcl::PointXYZ> extract;
extract.setInputCloud (cloud);
extract.setIndices (inliers_groud);
extract.setNegative(false);

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_groud (new pcl::PointCloud<pcl::PointXYZ>);

extract.filter (*cloud_groud);//get the ground plane

std::cerr << "Ground cloud after filtering: " << std::endl;
std::cerr << *cloud_groud << std::endl;

pcl::PCDWriter writer;
writer.write<pcl::PointXYZ> ("samp11-utm_ground.pcd", *cloud_groud, false);

我的回答:

看看这个PCL api:http://docs.pointclouds.org/1.7.2/a02405.html#ga4375e99ec2ae368eec9379f506568611

我成功解决了这个问题!

结果很好(紫色平面是原始地面,绿色平面是变换的地面,即X-O-Y平面):

现在如果 pcl::PointXYZ 是 (x0, y0, z0),那么 Mat (x0,y0) 上的点就是 z0。结果:

【问题讨论】:

  • 我终于在另一个问题中解决了这个问题:stackoverflow.com/questions/29841323/…
  • 请考虑将答案添加为答案,而不是作为问题的更新(编辑)。
  • 嗨!你能给我们使用 getTransformationFromTwoUnitVectorsAndOrigin 来获取 cvMat 的解决方案吗?谢谢!!
  • @EnneKappa 您无法通过getTransformationFromTwoUnitVectorsAndOrigin 获得 OpenCV Mat。 getTransformationFromTwoUnitVectorsAndOrigin API 使您的点云平面(这里是地平面)平行于 XOY 平面,然后您只需要一些编码工作(这很简单)将 pcl::PointXYZ (x0, y0, z0) 映射到Mat (x0,y0),即 z0。 cvMat 是旧的,使用 Mat。
  • @gouchaoer 你能给我看看 pastebin.com 的代码吗?我也有同样的情况。我想将点云投影到 2D 平面中的 IR 图像中

标签: c++ opencv kinect point-cloud-library


【解决方案1】:

当你在谈论的东西投射到地面 平面,通常是将需要的投影矩阵(K [R | T])。在 你的情况,如果我理解正确的话,你希望做一个正交 投影,这意味着你要失去Z坐标: http://en.wikipedia.org/wiki/Orthographic_projection

现在,你的情况下方程式将是这样的 P>

z_max = max z(Pts[x,y,z])
im[x,y] = z_max

注意在这里,你将需要搜索的最大高度(Z) 在您的云计算给定的X-Y点。

我希望这可以帮助你... P>

【讨论】:

  • 当然,我可以投射点到这样一个平面:pointclouds.org/documentation/tutorials/hull_2d.php 跨度>
  • 但我需要通过一个投射点的一个,以节省在地平面上的投影点的高度值。还我需要在地平面上变换投影点为二维的OpenCV垫格式。跨度>
  • 一次一个问题。我认为你的身高是Z轴,所以,在我的例子中,你会节省点的高度。 SPAN>
猜你喜欢
  • 1970-01-01
  • 2019-09-24
  • 1970-01-01
  • 1970-01-01
  • 2016-09-06
  • 2018-04-29
  • 1970-01-01
  • 2011-05-12
  • 1970-01-01
相关资源
最近更新 更多