最小割例题_dataframe分割数据

最小割例题_dataframe分割数据参考:https://www.cnblogs.com/ironstark/p/5008258.htmlhttps://github.com/Ewenwan/MVision/blob/master/PCL_APP/4_%E

参考:

https://www.cnblogs.com/ironstark/p/5008258.html

https://github.com/Ewenwan/MVision/blob/master/PCL_APP/4_%E7%82%B9%E4%BA%91%E5%88%86%E5%89%B2%E4%B8%8E%E5%88%86%E7%B1%BB%20Segmentation.md

最小割分割算法

算法对输入的点云进行二值分割,即分为两组:前景点和背景点(属于对象的点和不属于对象的点)

最小割(min-cut)并不是一个什么很新鲜的东西。它早就用在网络规划,求解桥问题,图像分割等领域,被移植到点云分割上也不足为奇。最小割算法是图论中的一个概念,其作用是以某种方式,将两个点分开,当然这两个点中间可能是通过无数的点再相连的。如图所示。

最小割例题_dataframe分割数据

  如果要分开最左边的点和最右边的点,红绿两种割法都是可行的,但是红线跨过了三条线,绿线只跨过了两条。单从跨线数量上来论可以得出绿线这种切割方法更优的结论。但假设线上有不同的权值,那么最优切割则和权值有关了。它到底是怎么找到那条绿线的暂且不论。总而言之,就是有那么一个算法,当你给出了点之间的 “图” (广义的),以及连线的权值时,最小割算法就能按照你的要求把图分开。

 

点云 “图”

  显而易见,切割有两个非常重要的因素,第一个是获得点与点之间的拓扑关系,也就是生成一张“图”。第二个是给图中的连线赋予合适的权值。只要这两个要素合适,最小割算法就会办好剩下的事情。点云是一种非常适合分割的对象(我第三次强调这个事情了),点云有天然分开的点。有了点之后,只要把点云中所有的点连起来就可以了。连接算法如下:

  1. 找到每个点最近的n个点
  2. 将这n个点和父点连接
  3. 找到距离最小的两个块(A块中某点与B块中某点距离最小),并连接
  4. 重复3,直至只剩一个块

  现在已经有了“图”,只要给图附上合适的权值,就完成了所有任务。物体分割给人一个直观印象就是属于该物体的点,应该相互之间不会太远。也就是说,可以用点与点之间的欧式距离来构造权值。所有线的权值可映射为线长的函数。

smoothCost=e^{-(\frac{dist}{ \sigma })^2}

  貌似我们现在已经搞定一切了,其实不然。分割总是有一个目标的,而这种精准打击的算法,显然你要告诉我打击对象是谁,打击范围多大——目标需要人为指定(center),尺寸需要提前给出(radius)。

  OK,我们现在有了打击对象了(指定了目标物体上的一个点),接下来要做的,就是让除此对象之外的物体被保护起来,不受到打击。保护的方法就是认为加重目标范围之外的权值(罚函数)

backgroundPenalty=(\frac{distanceToCenter}{radius})

     上述过程其实看起来还不够智能,如果有办法让我只需要点一下鼠标,选中要分割的物体,接下来电脑替我操心其他事情,那就太好了。这其实是可以实现的,称为AutoMatic Regime.但PCL并没有封装这个算法,忽略不表。

算法思想

The idea of this algorithm is as follows:

  1. For the given point cloud algorithm constructs the graph that contains every single point of the cloud as a set of vertices and two more vertices called source and sink. Every vertex of the graph that corresponds to the point is connected with source and sink with the edges. In addition to these, every vertex (except source and sink) has edges that connect the corresponding point with its nearest neighbours.

  2. Algorithm assigns weights for every edge. There are three different types of weight. Let’s examine them:

    • First of all it assigns weight to the edges between clouds points. This weight is called smooth cost and is calculated by the formula:

      smoothCost=e^{-(\frac{dist}{ \sigma })^2}

      Here dist is the distance between points. The farther away the points are, the more is probability that the edge will be cut.

    • Next step the algorithm sets data cost. It consists of foreground and background penalties. The first one is the weight for those edges that connect clouds points with the source vertex and has the constant user-defined value. The second one is assigned to the edges that connect points with the sink vertex and is calculated by the formula:

      backgroundPenalty=(\frac{distanceToCenter}{radius})

      Here distanceToCenter is the distance to the expected center of the object in the horizontal plane:

      distanceToCenter=\sqrt{(x-centerX)^2+(y-centerY)^2}

      Radius that occurs in the formula is the input parameter for this algorithm and can be roughly considered as the range from objects center outside of which there are no points that belong to foreground (objects horizontal radius).

 

PCL编程实现

http://pointclouds.org/documentation/tutorials/min_cut_segmentation.php#min-cut-segmentation

#include <iostream> #include <vector> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/visualization/cloud_viewer.h> #include <pcl/filters/passthrough.h> #include <pcl/segmentation/min_cut_segmentation.h> int main (int argc, char** argv) { pcl::PointCloud <pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud <pcl::PointXYZ>); if ( pcl::io::loadPCDFile <pcl::PointXYZ> ("min_cut_segmentation_tutorial.pcd", *cloud) == -1 ) { std::cout << "Cloud reading failed." << std::endl; return (-1); } pcl::IndicesPtr indices (new std::vector <int>); pcl::PassThrough<pcl::PointXYZ> pass; pass.setInputCloud (cloud); pass.setFilterFieldName ("z"); pass.setFilterLimits (0.0, 1.0); pass.filter (*indices); pcl::MinCutSegmentation<pcl::PointXYZ> seg; seg.setInputCloud (cloud); seg.setIndices (indices); pcl::PointCloud<pcl::PointXYZ>::Ptr foreground_points(new pcl::PointCloud<pcl::PointXYZ> ()); pcl::PointXYZ point; point.x = 68.97; point.y = -18.55; point.z = 0.57; foreground_points->points.push_back(point); seg.setForegroundPoints (foreground_points); seg.setSigma (0.25); seg.setRadius (3.0); seg.setNumberOfNeighbours (14); seg.setSourceWeight (0.8); std::vector <pcl::PointIndices> clusters; seg.extract (clusters); std::cout << "Maximum flow is " << seg.getMaxFlow () << std::endl; pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = seg.getColoredCloud (); pcl::visualization::CloudViewer viewer ("Cluster viewer"); viewer.showCloud(colored_cloud); while (!viewer.wasStopped ()) { } return (0); }

分割效果

_images/min_cut_segmentation.jpg

 

今天的文章
最小割例题_dataframe分割数据分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/89712.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注