PCL—低層次視覺—點雲分割(最小割算法)

1.前言

  基於採樣一致的點雲分割算法顯然是意識流的,它只能割出大概的點雲(,其只能事先知道要分割對象的表達式,纔可提取出目標,如提取水杯時,可能是杯子的一部分,但杯把兒肯定沒分割出來)。基於歐式算法的點雲分割面對有牽連的點雲就無力了,其主要依靠距離進行判斷連接(比如風箏和人,在不用三維形態學去掉中間的線之前,是無法分割風箏和人的)。基於法線等信息的區域生長算法則對平面更有效,沒法靠它來分割桌上的碗和杯子(近鄰點法向量夾角較大,區域增長時無法判斷對象具體形狀)。基於密度聚類分割算法,類似於歐式聚類,如放在桌子上的杯子,則無法準確提取出杯子。也就是說,上述算法更關注能不能分割,除此之外,我們還需要一個方法來解決分割的“好不好”這個問題。也就是說,有沒有哪種方法,可以在一個點不多,一個點不少的情況下,把目標和“其他”分開。

答案是有,也就是這篇博文要解決的最小割算法。

2.最小割算法

  最小割(min-cut)並不是一個什麼很新鮮的東西。它早就用在網絡規劃,求解橋問題,圖像分割等領域,被移植到點雲分割上也不足爲奇。最小割算法是圖論中的一個概念,其作用是以某種方式,將兩個點分開,當然這兩個點中間可能是通過無數的點再相連的。如圖所示。

  如果要分開最左邊的點和最右邊的點,紅綠兩種割法都是可行的,但是紅線跨過了三條線,綠線只跨過了兩條。單從跨線數量上來論可以得出綠線這種切割方法更優的結論。但假設線上有不同的權值,那麼最優切割則和權值有關了。它到底是怎麼找到那條綠線的暫且不論。總而言之,就是有那麼一個算法,當你給出了點之間的 “圖” (廣義的),以及連線的權值時,最小割算法就能按照你的要求把圖分開。

3.點雲 “圖”

  顯而易見,切割有兩個非常重要的因素,第一個是獲得點與點之間的拓撲關係,也就是生成一張“圖”。第二個是給圖中的連線賦予合適的權值。只要這兩個要素合適,最小割算法就會辦好剩下的事情。點雲是一種非常適合分割的對象(我第三次強調這個事情了),點雲有天然分開的點。有了點之後,只要把點雲中所有的點連起來就可以了。連接算法如下:

  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並沒有封裝這個算法,忽略不表。

4.PCL對最小割算法的實現

#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>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>
using namespace pcl::console;
int main()
{
	
	time_t start, end, diff[5], option;
	start = time(0);
	int NumberOfNeighbours = 14;//設置默認參數
	bool Bool_Cuting = false;//設置默認參數
	float far_cuting = 1, near_cuting = 0, C_x = 68.97, C_y = -18.55, C_z = 0.57, Sigma = 0.25, Radius = 0.8, SourceWeight = 0.5;//設置默認輸入參數
	pcl::PointCloud <pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud <pcl::PointXYZ>);// 創建一個PointCloud <pcl::PointXYZRGB>共享指針並進行實例化
	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>);//創建一組索引
	if (Bool_Cuting)//判斷是否需要直通濾波
	{
		pcl::PassThrough<pcl::PointXYZ> pass;//設置直通濾波器對象
		pass.setInputCloud(cloud);//設置輸入點雲
		pass.setFilterFieldName("z");//設置指定過濾的維度
		pass.setFilterLimits(near_cuting, far_cuting);//設置指定緯度過濾的範圍
		pass.filter(*indices);//執行濾波,保存濾波結果在上述索引中

	}

	//生成分割器
	pcl::MinCutSegmentation<pcl::PointXYZ> seg;
	//分割輸入分割目標
	seg.setInputCloud(cloud);
	//指定打擊目標(目標點)
	pcl::PointCloud<pcl::PointXYZ>::Ptr foreground_points(new    pcl::PointCloud<pcl::PointXYZ>());
	pcl::PointXYZ point;
	point.x = 66.34;
	point.y = -20;
	point.z = 1.18;
	foreground_points->points.push_back(point);
	seg.setForegroundPoints(foreground_points);
	//指定權函數sigma
	seg.setSigma(0.25);
	//物體大概範圍
	seg.setRadius(4.0433856);
	//用多少生成圖
	seg.setNumberOfNeighbours(14);
	//和目標點相連點的權值(至少有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::PCLVisualizer viewer("點雲庫PCL學習教程第二版-最小割分割方法");
	viewer.addPointCloud(colored_cloud,"sample");
	viewer.addSphere(point, Radius, 122, 122, 0, "sphere");
	viewer.setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY, 0.2, "sphere");
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample");

	while (!viewer.wasStopped())
	{
		viewer.spin();
	}//進行可視化

	return (0);
}

  顯然,最小割算法更注重分割的精確性而不是分割自動進行。最小割算法用於半自動分割識別有着巨大的優勢,適合用於計算機視覺,城市場景點雲分析一類。但對機器人來說,或許和特徵點檢測算法聯合起來能獲得較好的效果。

參考博文:https://www.cnblogs.com/ironstark/p/5008258.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章