PCL 點(diǎn)云濾波及分割匯總

點(diǎn)云濾波匯總

立方體濾波

首先是最簡(jiǎn)單的容易理解的立方體的剪裁濾波,根據(jù)對(duì)角點(diǎn)確定一個(gè)立方體然后獲取立方體內(nèi)或外的點(diǎn),并且還可以在這立方體基礎(chǔ)上加平移或旋轉(zhuǎn),因?yàn)楦鶕?jù)兩個(gè)點(diǎn)確立的立方體只是坐標(biāo)軸正方向的,不一定能滿足所有需求。

#include <pcl/filters/crop_box.h>
    /// <summary>
    /// 立方體濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="min">最小點(diǎn)位 x y z 1</param>
    /// <param name="max">最大點(diǎn)位 x y z 1</param>
    /// <param name="negative">默認(rèn)值為 false,輸出點(diǎn)云為在設(shè)定字段的設(shè)定范圍內(nèi)的點(diǎn)集,如果設(shè)置為 true 則剛好相反</param>
    void cropFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_out, Eigen::Vector4f &min, Eigen::Vector4f &max, bool negative) {
        pcl::CropBox<pcl::PointXYZ> box_filter;                     //濾波器對(duì)象
        box_filter.setMin(min); //Min和Max是指立方體的兩個(gè)對(duì)角點(diǎn)。每個(gè)點(diǎn)由一個(gè)四維向量表示,通常最后一個(gè)是1.
        box_filter.setMax(max);
        //box_filter.setRotation(rotation); //旋轉(zhuǎn) rx ry rz
        //box_filter.setTranslation(tanslation);//仿射矩陣 Affine3f 旋轉(zhuǎn)加平移
        //box_filter.setTransform(transformax);//平移 tx ty tz
        box_filter.setNegative(negative);
        box_filter.setInputCloud(cloud_in);
        box_filter.filter(*cloud_out);
    }

凸(凹)包濾波

這個(gè)濾波實(shí)際用下來效果就是把凸出來或凹進(jìn)去的一塊區(qū)域的點(diǎn)云濾出來,入?yún)⑵鋵?shí)輸不輸入都行就是維度,默認(rèn)不輸入就是按點(diǎn)云情況來,pcl::ConvexHull是用來算凸包的, pcl:: ConcaveHull用來算凹包,最后都扔到pcl::CropHull里面。

#include <pcl/surface/concave_hull.h>
#include <pcl/filters/crop_hull.h>

    /// <summary>
    /// 凸包濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="boundingbox">封閉區(qū)域頂點(diǎn)</param>
    /// <param name="dimension">設(shè)置凸包維度</param>
    /// <param name="negative">默認(rèn)值為 false,輸出點(diǎn)云為在設(shè)定字段的設(shè)定范圍內(nèi)的點(diǎn)集,如果設(shè)置為 true 則剛好相反</param>
    /// <param name="keepOrganized"> false=刪除點(diǎn)(默認(rèn)),true=重新定義點(diǎn),保留結(jié)構(gòu)</param>
    void cropHullFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_out, pcl::PointCloud<pcl::PointXYZ>::Ptr& boundingbox, int dimension, bool negative, bool keepOrganized) {
        pcl::PointCloud<pcl::PointXYZ>::Ptr surface_hull(new pcl::PointCloud<pcl::PointXYZ>);   //描述凸包形狀的點(diǎn)云
        std::vector<pcl::Vertices> polygons;// polygons保存的是所有凸包多邊形的頂點(diǎn)在surface_hull中的下標(biāo)

        pcl::ConvexHull<pcl::PointXYZ> hull;
        hull.setInputCloud(boundingbox);//設(shè)置輸入點(diǎn)云:封閉區(qū)域頂點(diǎn)點(diǎn)云
        hull.setDimension(dimension);//設(shè)置凸包維度

        //surface_hull存儲(chǔ)最終產(chǎn)生的凹多邊形上的頂點(diǎn),polygons存儲(chǔ)一系列頂點(diǎn)集,每個(gè)頂點(diǎn)集構(gòu)成的一個(gè)多邊形,Vertices數(shù)據(jù)結(jié)構(gòu)包含一組點(diǎn)的索引,索引是point中的點(diǎn)對(duì)應(yīng)的索引。
        hull.reconstruct(*surface_hull, polygons);

        pcl::CropHull<pcl::PointXYZ> CH;//創(chuàng)建CropHull濾波對(duì)象
        CH.setDim(dimension);   //設(shè)置維度,與凸包維度一致
        CH.setInputCloud(cloud_in);     //設(shè)置需要濾波的點(diǎn)云
        CH.setHullIndices(polygons);    //輸入封閉區(qū)域的頂點(diǎn)
        CH.setHullCloud(surface_hull);  //輸入封閉區(qū)域的形狀
        CH.setNegative(negative);
        CH.setKeepOrganized(keepOrganized);
        CH.filter(*cloud_out);
    }

體素采樣濾波

體素濾波可以按照給定長(zhǎng)寬高的立方體來填充點(diǎn)云,每個(gè)立方體的質(zhì)心點(diǎn)留下來以此讓減少點(diǎn)云中點(diǎn)的數(shù)目,有效的提升后續(xù)點(diǎn)云處理速度,一般用來下采樣。

#include <pcl/filters/voxel_grid.h>

    /// <summary>
    /// 體素采樣濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="lx">立方體X軸長(zhǎng)度</param>
    /// <param name="ly">立方體Y軸長(zhǎng)度</param>
    /// <param name="lz">立方體Z軸長(zhǎng)度</param>
    void voxelFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_out, float lx, float ly, float lz) {
        std::cout << "size before voxelFilter: " << cloud_in->size() << std::endl;
        pcl::VoxelGrid<pcl::PointXYZ> vox_grid;
        vox_grid.setLeafSize(lx, ly, lz);//設(shè)置濾波時(shí)創(chuàng)建的體素大小為lx m*ly m*lz m的立方體
        vox_grid.setInputCloud(cloud_in);
        vox_grid.filter(*cloud_out);
        std::cout << "size after voxelFilter: " << cloud_out->size() << std::endl;
    }

近似體素重心采樣濾波

ApproximateVoxelGrid近似體素濾波企圖以 更快的速度 實(shí)現(xiàn)與VoxelGrid 體素濾波相同的下采樣,它通過 散列函數(shù)(Hashing Function)快速逼近質(zhì)心,而不是精細(xì)確定質(zhì)心并對(duì)點(diǎn)云進(jìn)行下采樣。采樣結(jié)果是近似逼近的體素質(zhì)心,并不是體素中心。

#include <pcl/filters/approximate_voxel_grid.h>

    /// <summary>
    /// 近似體素重心采樣濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="lx">立方體X軸長(zhǎng)度</param>
    /// <param name="ly">立方體Y軸長(zhǎng)度</param>
    /// <param name="lz">立方體Z軸長(zhǎng)度</param>
    /// <param name="downsampleAllData">如果只有XYZ字段,則設(shè)置為false,如果對(duì)所有字段,如intensity,都進(jìn)行下采樣,則設(shè)置為true</param>
    void approximateVoxelGridFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_out, float lx, float ly, float lz, bool downsampleAllData) {
        std::cout << "size before voxelFilter: " << cloud_in->size() << std::endl;
        pcl::ApproximateVoxelGrid<pcl::PointXYZ> vox_grid;
        vox_grid.setLeafSize(lx, ly, lz);//設(shè)置濾波時(shí)創(chuàng)建的體素大小為lx m*ly m*lz m的立方體
        vox_grid.setInputCloud(cloud_in);
        vox_grid.setDownsampleAllData(downsampleAllData);
        vox_grid.filter(*cloud_out);
        std::cout << "size after voxelFilter: " << cloud_out->size() << std::endl;
    }

均勻采樣濾波

均勻采樣濾波原理和體素濾波是很相似的,但是體素采用單位立方體,而均勻采樣取給定半徑的球體內(nèi)的點(diǎn)保留質(zhì)心。

#include <pcl/filters/uniform_sampling.h>

    /// <summary>
    /// 均勻采樣濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="radius_seach">半徑范圍內(nèi)搜尋鄰居點(diǎn)</param>
    void uniformSamplingFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_out, double radius_seach) {
        pcl::UniformSampling<pcl::PointXYZ> filter;
        filter.setRadiusSearch(radius_seach);
        filter.setInputCloud(cloud_in);
        filter.filter(*cloud_out);
    }

隨機(jī)采樣濾波

隨機(jī)選擇n個(gè)點(diǎn),每個(gè)點(diǎn)被選到的概率相同,可以得到固定的點(diǎn)數(shù)量;
缺點(diǎn):如果原點(diǎn)云是不均勻的,比如有的地方密度大,有的地方密度小,那么RandomSample采樣后的點(diǎn)云同樣是不均勻的,分布同云點(diǎn)云。雖然每個(gè)點(diǎn)被選到的概率一樣,但密度大的區(qū)域內(nèi)點(diǎn)比較多,這個(gè)區(qū)域內(nèi)被采樣的機(jī)會(huì)就更多,因此原來密度大的地方,采樣后,密度還是大。

#include <pcl/filters/random_sample.h>

    /// <summary>
    /// 隨機(jī)采樣濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="sample">設(shè)置下采樣點(diǎn)云的點(diǎn)數(shù)</param>
    /// <param name="seed">隨機(jī)函數(shù)種子點(diǎn)</param>
    /// <param name="negative">默認(rèn)值為 false,輸出點(diǎn)云為在設(shè)定字段的設(shè)定范圍內(nèi)的點(diǎn)集,如果設(shè)置為 true 則剛好相反</param>
    /// <param name="keepOrganized"> false=刪除點(diǎn)(默認(rèn)),true=重新定義點(diǎn),保留結(jié)構(gòu)</param>
    void randomSamplingFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_out, unsigned int sample, unsigned int seed, bool negative, bool keepOrganized) {
        pcl::RandomSample<pcl::PointXYZ> filter;
        filter.setSample(sample);
        filter.setSeed(seed);
        filter.setNegative(negative);
        filter.setKeepOrganized(keepOrganized);
        filter.setInputCloud(cloud_in);
        filter.filter(*cloud_out);
    }

移動(dòng)最小二乘增采樣濾波

增采樣是一種表面重建方法,當(dāng)你有比你想象的要少的點(diǎn)云數(shù)據(jù)時(shí),增采樣可以幫你恢復(fù)原有的表面(S),通過內(nèi)插你目前擁有的點(diǎn)云數(shù)據(jù),這是一個(gè)復(fù)雜的猜想假設(shè)的過程。所以構(gòu)建的結(jié)果不會(huì)百分之一百準(zhǔn)確,但有時(shí)它是一種可選擇的方案。所以,在你的點(diǎn)云云進(jìn)行下采樣時(shí),一定要保存一份原始數(shù)據(jù)!

#include <pcl/surface/mls.h>

    /// <summary>
    /// 移動(dòng)最小二乘增采樣濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="tree">提取搜索方法的樹對(duì)象,一般用近鄰的kdTree即可</param>
    /// <param name="upsamplingMethod">Upsampling 采樣的方法有 DISTINCT_CLOUD, RANDOM_UNIFORM_DENSITY</param>
    /// <param name="searchRadius">設(shè)置搜索鄰域的半徑</param>
    /// <param name="upsamplingRadius">采樣的半徑</param>
    /// <param name="upsamplingStepSize">采樣步數(shù)的大小</param>
    void movingLeastSquaresFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_out, pcl::search::Search<pcl::PointXYZ>::Ptr tree, pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointXYZ>::UpsamplingMethod upsamplingMethod, double searchRadius, double upsamplingRadius, double upsamplingStepSize) {
        pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointXYZ> filter;
        filter.setInputCloud(cloud_in);
        filter.setSearchMethod(tree);
        //設(shè)置搜索鄰域的半徑
        filter.setSearchRadius(searchRadius);
        // Upsampling 采樣的方法有 DISTINCT_CLOUD, RANDOM_UNIFORM_DENSITY
        filter.setUpsamplingMethod(upsamplingMethod);
        // 采樣的半徑
        filter.setUpsamplingRadius(upsamplingRadius);
        // 采樣步數(shù)的大小
        filter.setUpsamplingStepSize(upsamplingStepSize);
        filter.process(*cloud_out);
    }

深度傳感器的測(cè)量是不準(zhǔn)確的,和由此產(chǎn)生的點(diǎn)云也是存在的測(cè)量誤差,比如離群點(diǎn),孔等表面,可以用一個(gè)算法重建表面,遍歷所有的點(diǎn)云和插值數(shù)據(jù),試圖重建原來的表面。

統(tǒng)計(jì)濾波

統(tǒng)計(jì)濾波器用于去除明顯離群點(diǎn)(離群點(diǎn)往往由測(cè)量噪聲引入)。
其特征是在空間中分布稀疏,可以理解為:每個(gè)點(diǎn)都表達(dá)一定信息量,某個(gè)區(qū)域點(diǎn)越密集則可能信息量越大。噪聲信息屬于無用信息,信息量較小。所以離群點(diǎn)表達(dá)的信息可以忽略不計(jì)??紤]到離群點(diǎn)的特征,則可以定義某處點(diǎn)云小于某個(gè)密度,既點(diǎn)云無效。計(jì)算每個(gè)點(diǎn)到其最近的k(設(shè)定)個(gè)點(diǎn)平均距離。則點(diǎn)云中所有點(diǎn)的距離應(yīng)構(gòu)成高斯分布。給定均值與方差,可剔除n個(gè)西格瑪之外的點(diǎn)

激光掃描通常會(huì)產(chǎn)生密度不均勻的點(diǎn)云數(shù)據(jù)集,另外測(cè)量中的誤差也會(huì)產(chǎn)生稀疏的離群點(diǎn),此時(shí),估計(jì)局部點(diǎn)云特征(例如采樣點(diǎn)處法向量或曲率變化率)時(shí)運(yùn)算復(fù)雜,這會(huì)導(dǎo)致錯(cuò)誤的數(shù)值,反過來就會(huì)導(dǎo)致點(diǎn)云配準(zhǔn)等后期的處理失敗。
解決辦法:對(duì)每個(gè)點(diǎn)的鄰域進(jìn)行一個(gè)統(tǒng)計(jì)分析,并修剪掉一些不符合標(biāo)準(zhǔn)的點(diǎn)。
具體方法為在輸入數(shù)據(jù)中對(duì)點(diǎn)到臨近點(diǎn)的距離分布的計(jì)算,對(duì)每一個(gè)點(diǎn),
計(jì)算它到所有臨近點(diǎn)的平均距離(假設(shè)得到的結(jié)果是一個(gè)高斯分布,
其形狀是由均值和標(biāo)準(zhǔn)差決定),那么平均距離在標(biāo)準(zhǔn)范圍之外的點(diǎn),
可以被定義為離群點(diǎn)并從數(shù)據(jù)中去除。

#include <pcl/filters/statistical_outlier_removal.h>

    /// <summary>
    /// 統(tǒng)計(jì)濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="meanK">K近鄰搜索點(diǎn)個(gè)數(shù)</param>
    /// <param name="std_dev_mul">標(biāo)準(zhǔn)差倍數(shù)</param>
    /// <param name="negative">默認(rèn)值為 false,輸出點(diǎn)云為在設(shè)定字段的設(shè)定范圍內(nèi)的點(diǎn)集,如果設(shè)置為 true 則剛好相反</param>
    /// <param name="keepOrganized"> false=刪除點(diǎn)(默認(rèn)),true=重新定義點(diǎn),保留結(jié)構(gòu)</param>
    void sorFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_out, int meanK, float std_dev_mul,bool negative, bool keepOrganized) {
        std::cout << "size before statisticalOutlierRemoval: " << cloud_in->size() << std::endl;
        pcl::StatisticalOutlierRemoval<pcl::PointXYZ> filter(true);
        filter.setInputCloud(cloud_in);
        filter.setMeanK(meanK);
        filter.setStddevMulThresh(std_dev_mul);
        filter.setNegative(negative);
        filter.setKeepOrganized(keepOrganized);
        filter.filter(*cloud_out);
        std::cout << "size after statisticalOutlierRemoval: " << cloud_out->size() << std::endl;
    }

半徑濾波

球半徑濾波器與統(tǒng)計(jì)濾波器相比更加簡(jiǎn)單粗暴。
以某點(diǎn)為中心 畫一個(gè)球計(jì)算落在該球內(nèi)的點(diǎn)的數(shù)量,當(dāng)數(shù)量大于給定值時(shí),
則保留該點(diǎn),數(shù)量小于給定值則剔除該點(diǎn)。
此算法運(yùn)行速度快,依序迭代留下的點(diǎn)一定是最密集的,
但是球的半徑和球內(nèi)點(diǎn)的數(shù)目都需要人工指定。

#include <pcl/filters/radius_outlier_removal.h>

    /// <summary>
    /// 半徑濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="radiusSearch">半徑范圍內(nèi)搜尋鄰居點(diǎn)</param>
    /// <param name="minNeighborsInRadius">鄰居少于點(diǎn)數(shù)認(rèn)為是離群點(diǎn)</param>
    /// <param name="negative">默認(rèn)值為 false,輸出點(diǎn)云為在設(shè)定字段的設(shè)定范圍內(nèi)的點(diǎn)集,如果設(shè)置為 true 則剛好相反</param>
    /// <param name="keepOrganized"> false=刪除點(diǎn)(默認(rèn)),true=重新定義點(diǎn),保留結(jié)構(gòu)</param>
    void rorFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_out, int radiusSearch, float minNeighborsInRadius, bool negative, bool keepOrganized) {
        std::cout << "size before radiusOutlierRemoval: " << cloud_in->size() << std::endl;

        pcl::RadiusOutlierRemoval<pcl::PointXYZ> ror;
        ror.setInputCloud(cloud_in);
        ror.setRadiusSearch(radiusSearch);
        ror.setMinNeighborsInRadius(minNeighborsInRadius);
        ror.setNegative(negative);
        ror.setKeepOrganized(keepOrganized);
        ror.filter(*cloud_out);

        std::cout << "size after radiusOutlierRemoval: " << cloud_out->size() << std::endl;

    }

直通濾波

直通濾波是直接根據(jù)某一個(gè)軸的最大最小值,直接過濾出在這范圍里的點(diǎn)云

#include <pcl/filters/passthrough.h>

    /// <summary>
    /// 直通濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="field_name">坐標(biāo)軸名稱:x ,y ,z</param>
    /// <param name="limit_min">最大值</param>
    /// <param name="limit_max">最小值</param>
    /// <param name="negative">默認(rèn)值為 false,輸出點(diǎn)云為在設(shè)定字段的設(shè)定范圍內(nèi)的點(diǎn)集,如果設(shè)置為 true 則剛好相反</param>
    void passThroughFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_out, const std::string &field_name, const float &limit_min, const float &limit_max, bool negative) {
        pcl::PassThrough<pcl::PointXYZ> pass;
        pass.setInputCloud(cloud_in);            //設(shè)置輸入點(diǎn)云
        pass.setFilterFieldName(field_name);         //設(shè)置過濾時(shí)所需要點(diǎn)云類型的字符串字段 "x" "y" "z"
        pass.setFilterLimits(limit_min, limit_max);        //設(shè)置在過濾字段的范圍
        pass.setFilterLimitsNegative (negative);   //設(shè)置保留范圍內(nèi)還是過濾掉范圍內(nèi)
        pass.filter(*cloud_out);            //執(zhí)行濾波,保存過濾結(jié)果在cloud_out

    }

條件濾波

條件濾波相比直通濾波更加靈活的設(shè)置各種值范圍過濾點(diǎn)云,用pcl::ConditionAnd創(chuàng)建與條件,用pcl::ConditionOr創(chuàng)建或條件,最后扔到pcl::ConditionalRemoval里。

#include <pcl/filters/conditional_removal.h>

    /// <summary>
    /// 條件濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="range_cond">條件范圍</param>
    /// <param name="keepOrganized">false=刪除點(diǎn)(默認(rèn)),true=重新定義點(diǎn),保留結(jié)構(gòu)</param>
    void conditionalRemovalFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_out, ConditionBaseT::Ptr condition, bool keepOrganized) {
        //pcl::ConditionAnd<pcl::PointXYZ>::Ptr condition(new pcl::ConditionAnd<pcl::PointXYZ>());//創(chuàng)建與條件
        //pcl::ConditionOr表示或條件
        //condition->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new
        //  pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::GT, 0.0)));
        //condition->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new
        //  pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::LT, 0.8)));
        //GT表示大于等于,LT表示小于等于,EQ表示等于,GE表示大于,LE表示小于
        pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
        condrem.setCondition(condition);
        condrem.setInputCloud(cloud_in);
        condrem.setKeepOrganized(keepOrganized);
        condrem.filter(*cloud_out);
    }

投影濾波

投影濾波比較高級(jí)用的比較多的是向一個(gè)平面投影,很多時(shí)候把3維的數(shù)據(jù)降維到2維很多復(fù)雜的處理都能因此變得簡(jiǎn)單,標(biāo)準(zhǔn)的降維打擊,設(shè)置ModelType類型為pcl::SACMODEL_PLANE,按照平面方程公式ax+by+cz+d=0,把a(bǔ),b,c,d值依次放入pcl::ModelCoefficients類型對(duì)象中即可。

#include <pcl/filters/project_inliers.h>
#include <pcl/ModelCoefficients.h>

    /// <summary>
    /// 投影濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="coefficients">設(shè)置模型對(duì)應(yīng)的系數(shù),類似數(shù)組提供coefficients->values.resize(n)定義大小,coefficients->values[0]=賦值,平面的話值對(duì)應(yīng)ax+by+cz+d=0</param>
    /// <param name="modelType">設(shè)置對(duì)應(yīng)的投影模型,平面用pcl::SACMODEL_PLANE</param>
    void projectInliersFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_out, pcl::ModelCoefficients::Ptr &coefficients, int modelType) {

        pcl::ProjectInliers<pcl::PointXYZ> proj;        //創(chuàng)建投影濾波對(duì)象
        proj.setModelType(modelType);           //設(shè)置對(duì)象對(duì)應(yīng)的投影模型
        proj.setInputCloud(cloud_in);           //設(shè)置輸入點(diǎn)云
        proj.setModelCoefficients(coefficients);        //設(shè)置模型對(duì)應(yīng)的系數(shù)
        proj.filter(*cloud_out);    //執(zhí)行投影濾波存儲(chǔ)結(jié)果cloud_projected

    }

雙邊濾波

雙邊濾波利用的并非XYZ字段的數(shù)據(jù)進(jìn)行,而是利用強(qiáng)度數(shù)據(jù)字段進(jìn)行雙邊濾波算法的實(shí)現(xiàn),所以在使用該類時(shí)點(diǎn)云的類型中字段必須有強(qiáng)度字段,否則無法進(jìn)行雙邊濾波處理。

#include <pcl/filters/bilateral.h>

    /// <summary>
    /// 雙邊濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="sigma_s">高斯雙邊濾波窗口大小</param>
    /// <param name="sigma_r">高斯標(biāo)準(zhǔn)差表示強(qiáng)度差異</param>
    /// <param name="tree">提取搜索方法的樹對(duì)象,一般用近鄰的kdTree即可</param>
    void bilateralFilter(pcl::PointCloud<pcl::PointXYZI>::Ptr& cloud_in, pcl::PointCloud<pcl::PointXYZI>::Ptr& cloud_out, const float& sigma_s, const float& sigma_r, pcl::search::Search<pcl::PointXYZI>::Ptr tree) {
        pcl::BilateralFilter<pcl::PointXYZI> bf;
        bf.setInputCloud(cloud_in);            //設(shè)置輸入點(diǎn)云
        bf.setSearchMethod(tree);
        bf.setHalfSize(sigma_s);
        bf.setStdDev(sigma_r);
        bf.filter(*cloud_out);
    }

#include <pcl/filters/fast_bilateral.h>

    /// <summary>
    /// 快速雙邊濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="sigma_s">高斯雙邊濾波窗口大小</param>
    /// <param name="sigma_r">高斯標(biāo)準(zhǔn)差表示強(qiáng)度差異</param>
    void fastBilateralFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_out, const float& sigma_s, const float& sigma_r) {
        pcl::FastBilateralFilter<pcl::PointXYZ> fbf;
        fbf.setInputCloud(cloud_in);            //設(shè)置輸入點(diǎn)云
        fbf.setSigmaS(sigma_s);
        fbf.setSigmaR(sigma_r);
        fbf.filter(*cloud_out);
    }

索引濾波

根據(jù)點(diǎn)云給定索引過濾出對(duì)應(yīng)點(diǎn)云,一般不會(huì)單獨(dú)用,都是配合一些特征提取完對(duì)應(yīng)索引后來用。

#include <pcl/filters/extract_indices.h>

    /// <summary>
    /// 索引濾波
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cloud_out">輸出點(diǎn)云</param>
    /// <param name="indices">過濾的點(diǎn)云索引</param>
    /// <param name="negative">默認(rèn)值為 false,輸出點(diǎn)云為在設(shè)定字段的設(shè)定范圍內(nèi)的點(diǎn)集,如果設(shè)置為 true 則剛好相反</param>
    void extractIndicesFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_out, pcl::PointIndices::Ptr &indices, bool negative) {

        pcl::ExtractIndices<pcl::PointXYZ> extract;
        extract.setInputCloud(cloud_in);
        extract.setIndices(indices);
        extract.setNegative(negative);
        extract.filter(*cloud_out);
    }

總結(jié)

一般場(chǎng)景這些濾波組合能解決95%的應(yīng)用場(chǎng)景,其他的濾波應(yīng)用場(chǎng)景是在很少如pcl::BoxClipper3D用來空間剪裁也可以指定立方體,pcl::filters::Convolution是卷積濾波設(shè)置卷積核,pcl::filters::GaussianKernelpcl::filters::GaussianKernelRGB是高斯卷積核濾波,基本其他這些在實(shí)際場(chǎng)景里很少用到

點(diǎn)云分割匯總

這里的分割結(jié)果基本為索引再配合上問的索引濾波可以提取出對(duì)應(yīng)點(diǎn)云。

歐式距離分割

歐式距離分割是基于歐氏距離進(jìn)行聚類分割的類,這里注意這個(gè)類pcl::gpu::EuclideanClusterExtraction這么寫會(huì)在gpu上跑,而pcl::EuclideanClusterExtraction這么寫則會(huì)在cpu上,這類寫法同樣適用pcl內(nèi)其他的類,另外還有一些別的歐式聚類的類看名稱就能猜到用途,如LabeledEuclideanClusterExtraction就是多了一個(gè)setMaxLabels設(shè)置點(diǎn)云標(biāo)簽的最大數(shù)量。

這個(gè)方法用的也算頻繁的,大部分場(chǎng)景 下采樣-歐式聚類-投影,這時(shí)候就直接變二維圖像了,opencv提取個(gè)輪廓基本工業(yè)場(chǎng)景的視覺要做的就完成了很大一部分。

#include <pcl/segmentation/extract_clusters.h>

    /// <summary>
    /// 歐式距離分割
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cluster_indices_out">輸出索引</param>
    /// <param name="tolerance">近鄰搜索的搜索半徑 m</param>
    /// <param name="min_cluster_size">一個(gè)聚類需要的最少點(diǎn)數(shù)目</param>
    /// <param name="max_cluster_size">一個(gè)聚類需要的最大點(diǎn)數(shù)目</param>
    void euclideanClusterExtraction(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_in, std::vector<pcl::PointIndices> &cluster_indices_out, double tolerance, int min_cluster_size, int max_cluster_size) {
        // 創(chuàng)建用于提取搜索方法的kdtree樹對(duì)象
        pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
        tree->setInputCloud(cloud_in);

        pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;      //歐式聚類對(duì)象
        ec.setClusterTolerance(tolerance);                      // 設(shè)置近鄰搜索的搜索半徑為tolerance m
        ec.setMinClusterSize(min_cluster_size);                     //設(shè)置一個(gè)聚類需要的最少的點(diǎn)數(shù)目為100
        ec.setMaxClusterSize(max_cluster_size);                 //設(shè)置一個(gè)聚類需要的最大點(diǎn)數(shù)目為200000
        ec.setSearchMethod(tree);                       //設(shè)置點(diǎn)云的搜索機(jī)制
        ec.setInputCloud(cloud_in);
        ec.extract(cluster_indices_out);                    //從點(diǎn)云中提取聚類,并將點(diǎn)云索引保存在cluster_indices中
    }

采樣一致性分割

采樣一致性分割算法的目的主要是從原點(diǎn)云中提取目標(biāo)模型,比如說面,球體,圓柱等等,從而為后續(xù)的目標(biāo)識(shí)別或者點(diǎn)云匹配等等做準(zhǔn)備。這里只詳細(xì)講比較有代表性的pcl::SACSegmentation,這一類還有SACSegmentationFromNormals其在算法實(shí)現(xiàn)時(shí)采用了法線信息,即該類在進(jìn)行運(yùn)算輸出之前需要設(shè)定法線信息。

采樣一致性算法
1. 隨機(jī)采樣一致性算法(SAC_RANSAC)

pcl::RandomSampleConsensus< PointT > Class Template Reference
RandomSampleConsensus 表示隨機(jī)采樣一致性算法的實(shí)現(xiàn),該算法的工作原理如下:
從云中隨機(jī)選擇樣本,數(shù)量與確定模型所需的數(shù)量一樣多;
從樣本中計(jì)算模型的系數(shù);
在給定閾值的情況下,計(jì)算云中有多少點(diǎn)屬于模型。 這些被稱為內(nèi)點(diǎn);
重復(fù)直到找到一個(gè)好的模型或達(dá)到最大迭代次數(shù),返回具有最多內(nèi)點(diǎn)的模型。

2. 最小平方中值算法(SAC_LMEDS)

pcl::LeastMedianSquares< PointT > Class Template Reference
LeastMedianSquares 為最小平方中值算法的實(shí)現(xiàn)。LMedS 是一種類似于 RANSAC 的模型擬合算法,可以容忍高達(dá) 50% 的異常值,而無需設(shè)置閾值。與 RANSAC 相比,LMedS 在查找模型時(shí)不會(huì)將點(diǎn)分為內(nèi)點(diǎn)和異常點(diǎn)。 相反,它使用所有點(diǎn)模型距離的中值作為模型好壞的衡量標(biāo)準(zhǔn)。 只有在最后確定哪些點(diǎn)屬于找到的模型時(shí)才需要一個(gè)閾值。

3. M-估計(jì)量樣本一致性算法(SAC_MSAC)

pcl::MEstimatorSampleConsensus< PointT > Class Template Reference
MEstimatorSampleConsensus 表示 M-估計(jì)量樣本一致性算法的實(shí)現(xiàn)。RANSAC 在給定閾值的情況下計(jì)算內(nèi)點(diǎn)數(shù)。 內(nèi)點(diǎn)越多,模型越好——內(nèi)點(diǎn)與模型的實(shí)際距離有多近并不重要,只要它們?cè)陂撝祪?nèi)即可。 MSAC 通過使用所有點(diǎn)模型距離的總和作為質(zhì)量度量來改變這一點(diǎn),但是異常值僅添加閾值而不是它們的真實(shí)距離。 與 RANSAC 相比,這種方法可以產(chǎn)生更好的結(jié)果。

4. 快點(diǎn)的隨機(jī)采樣一致性算法(SAC_RRANSAC)

pcl::RandomizedRandomSampleConsensus< PointT > Class Template Reference
RandomizedRandomSampleConsensus 表示 RRANSAC的實(shí)現(xiàn),該算法的工作原理與 RANSAC 類似,但有一個(gè)補(bǔ)充:計(jì)算模型系數(shù)后,隨機(jī)選擇一小部分點(diǎn);如果這些點(diǎn)中的任何一個(gè)點(diǎn)在給定的閾值內(nèi)不屬于擬合模型,則繼續(xù)下一次迭代,而不是檢查所有點(diǎn)。 如果預(yù)先測(cè)試的分?jǐn)?shù)選擇得當(dāng),則可能會(huì)加快模型的擬合速度。

5. 隨機(jī)M-估計(jì)量樣本一致性(SAC_RMSAC)

pcl::RandomizedMEstimatorSampleConsensus< PointT > Class Template Reference
RandomizedMEstimatorSampleConsensus 表示 隨機(jī)M-估計(jì)量樣本一致性算法的實(shí)現(xiàn),RMSAC 在大部分樣本數(shù)據(jù)屬于模型的情況下很有用。是MEstimatorSampleConsensus和RandomizedRandomSampleConsensus的綜合版本,首先隨機(jī)選取一些采樣點(diǎn),如果這些點(diǎn)中的任何一個(gè)點(diǎn)在給定閾值范圍內(nèi)不屬于待擬合的模型,則繼續(xù)下一次迭代,而不是檢查所有點(diǎn)。同時(shí)使用所有點(diǎn)模型距離的總和作為質(zhì)量度量來改變這一點(diǎn),異常值僅添加閾值而不是它們的真實(shí)距離。

6. 最大似然估計(jì)樣本一致性算法(SAC_MLESAC)

pcl::MaximumLikelihoodSampleConsensus< PointT > Class Template Reference
MaximumLikelihoodSampleConsensus 表示 最大似然估計(jì)樣本一致性算法的實(shí)現(xiàn)。通過最小化概率損失作為評(píng)價(jià)指標(biāo)。使用由內(nèi)點(diǎn)和外點(diǎn)產(chǎn)生的誤差的概率模型來評(píng)估模型的適應(yīng)性,選取模型適應(yīng)性最高的模型參數(shù)作為最終結(jié)果。

7. 漸進(jìn)樣本一致性算法(SAC_PROSAC)

pcl::ProgressiveSampleConsensus< PointT > Class Template Reference
ProgressiveSampleConsensus 表示 漸進(jìn)樣本一致性算法的實(shí)現(xiàn),漸進(jìn)一致性算法 (PROSAC) 是對(duì)經(jīng)典 RANSAC采樣的一種優(yōu)化。相比經(jīng)典 RANSAC 方法均勻地從整個(gè)樣本集合中采樣,PROSAC 不是從所有數(shù)據(jù)點(diǎn)中進(jìn)行隨機(jī)采樣,而是先對(duì)數(shù)據(jù)點(diǎn)進(jìn)行排序,然后在評(píng)價(jià)函數(shù)值最高的數(shù)據(jù)點(diǎn)子集中進(jìn)行隨機(jī)采樣。該方法從采樣點(diǎn)的選取方式入手,選擇評(píng)價(jià)函數(shù)值最高的數(shù)據(jù)進(jìn)行隨機(jī)采樣。所以這種方法可以節(jié)省計(jì)算量,提高運(yùn)行速度。

采樣一致性的幾何模型的類型
SACMODEL_PLANE模型

定義為平面模型,共設(shè)置4個(gè)參數(shù)[ normal_x, normal_y, normal_z d],其中(normal_x, normal_y, normal_z)為Hessian 范式中法向量的坐標(biāo)及常量d值,ax+by+cz+d=0,從點(diǎn)云中分割提取的內(nèi)點(diǎn)都處在估計(jì)參數(shù)對(duì)應(yīng)的平面上或與平面距離在一定范圍內(nèi)。

SACMODEL_LINE模型

定義為直線模型,共設(shè)置6個(gè)參數(shù)[point_on_line.x, point_on_line.y, point_on_line.z, line_direction.x, line_direction.y, line_direction.z],其中(point_on_line.x,point_on_line.y,point_on_line.z)為直線上一點(diǎn)的三維坐標(biāo),(line_direction.x, line_direction.y, line_direction.z)為直線方向向量的三維坐標(biāo),從點(diǎn)云中分割提取的內(nèi)點(diǎn)都處在估計(jì)參數(shù)對(duì)應(yīng)直線上或與直線的距離在一定范圍內(nèi)。

SACMODEL_CIRCLE2D模型

定義為二維圓的圓周模型,共設(shè)置3個(gè)參數(shù)[center.x, center.y, radius],其中(center.x, center.y)為圓周中心點(diǎn)的二維坐標(biāo),radius為圓周半徑,從點(diǎn)云中分割提取的內(nèi)點(diǎn)都處在估計(jì)參數(shù)對(duì)應(yīng)的圓周上或距離圓周邊線的距離在一定范圍內(nèi)。

SACMODEL_SPHERE模型

定義為三維球體模型,共設(shè)置4個(gè)參數(shù)[center.x, center.y, center.z radius],其中(center. x, center. y, center. z)為球體中心的三維坐標(biāo),radius為球體半徑,從點(diǎn)云中分割提取的內(nèi)點(diǎn)都處在估計(jì)參數(shù)對(duì)應(yīng)的球體上或距離球體邊線的距離在一定范圍內(nèi)。

SACMODEL_NORMAL_SPHERE模型

定義為有條件限制的三維球體模型,參數(shù)設(shè)置參見SampleConsensusModelNormalSphere模型。

SACMODEL_CYLINDER模型

定義為圓柱體模型,共設(shè)置7個(gè)參數(shù)[point_on_axis.x, point_on_axis.y, point_on_axis.z, axis_direction.x ,axis_direction.y ,axis_diection.z, radius],其中,(point_on_axis.x, point_on_axis.y, point_on_axis.z)為軸線上點(diǎn)的三維坐標(biāo),(direction.x ,axis_direction.y, axis_direction.z)為軸線方向向量的三維坐標(biāo),radius為圓柱體半徑,從點(diǎn)云中分割提取的內(nèi)點(diǎn)都處在估計(jì)參數(shù)對(duì)應(yīng)的圓柱體上或距離圓柱體表面的距離在一定范圍內(nèi)。

SACMODEL_CONE模型

定義為圓錐模型,共設(shè)置7個(gè)參數(shù)[apex.x, apex.y, apex.z, axis_direction.x, axis_direction.y, axis_direction.z, opening_angle],其中(apex.x, apex.y, apex.z)圓錐頂點(diǎn),(axis_direction.x, axis_direction.y, axis_direction.z)為圓錐軸方向的三維坐標(biāo),opening_angle為圓錐的開口角度

SACMODEL_TORUS模型

定義為圓環(huán)面模型,尚未實(shí)現(xiàn)。

SACMODEL_PARALLEL_LINE 模型

定義為有條件限制的直線模型,在規(guī)定的最大角度偏差限制下,直線模型與給定軸線平行,共設(shè)置6個(gè)參數(shù)[point_on_line.x, point_on_line.y, point_on_line.z, line_direction.x, line_direction.y, line_direction.z],其中(point_on_line.x, point_on_line.y, point_on_line.z)為線上一個(gè)點(diǎn)的三維坐標(biāo),(line_direction.x, line_direction.y, line_direction.z)為直線方向的三維坐標(biāo)。

SACMODEL_PERPENDICULAR_PLANE模型

定義為有條件限制的平面模型,在規(guī)定的最大角度偏差限制下,平面模型與給定軸線垂直,參數(shù)設(shè)置參見SAC-MODEL_PLANE模型。

SACMODEL_NORMAL_PLANE模型

定義為有條件限制的平面模型,在規(guī)定的最大角度偏差限制下,每一個(gè)局內(nèi)點(diǎn)的法線必須與估計(jì)的平面模型的法線平行,參數(shù)設(shè)置參見SACMODEL_PLANE模型。

SACMODEL_PARALLEL_PLANE模型

定義為有條件限制的平面模型,在規(guī)定的最大角度偏差限制下,平面模型與給定的軸線平行,參數(shù)設(shè)置參見SACMODEL_PLANE模型。

SACMODEL_NORMAL_PARALLEL_PLANE模型

定義為有條件限制的平面模型,在法線約束下,三維平面模型必須與用戶設(shè)定的軸線平行,共4個(gè)參數(shù)[a,b,c,d],其中a是平面法線的 X 坐標(biāo)(歸一化),b是平面法線的 Y 坐標(biāo)(歸一化),c是平面法線的 Z 坐標(biāo)(歸一化),d是平面方程的第四個(gè) Hessian 分量。

SACMODEL_STICK模型

定義棒是用戶給定最小/最大寬度的線。共7個(gè)參數(shù)[point_on_line.x, point_on_line.y, point_on_line.z, line_direction.x, line_direction.y, line_direction.z, line_width],其中(point_on_line.x, point_on_line.y, point_on_line.z)為線上一個(gè)點(diǎn)的三維坐標(biāo),(line_direction.x, line_direction.y, line_direction.z)為直線方向的三維坐標(biāo),line_width為線的寬度。

具體實(shí)現(xiàn)

#include <pcl/segmentation/sac_segmentation.h>

    /// <summary>
    /// 一致性分割
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cluster_indices_out">輸出索引</param>
    /// <param name="coefficients_out">輸出模型</param>
    /// <param name="methodType">采樣一致性方法的類型</param>
    /// <param name="modelType">采樣一致性所構(gòu)造的幾何模型的類型</param>
    /// <param name="distance">點(diǎn)到模型的距離閾值</param>
    /// <param name="max_iterations">迭代次數(shù)的上限</param>
    /// <param name="probability">選取至少一個(gè)局內(nèi)點(diǎn)的概率</param>
    void sacSegmentationExtraction(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_in, int methodType, pcl::SacModel modelType, double distance, int max_iterations, double probability, pcl::PointIndices &cluster_indices_out, pcl::ModelCoefficients &coefficients_out) {
        pcl::SACSegmentation<pcl::PointXYZ> sac;        //一致性分割
        sac.setInputCloud(cloud_in);
        //設(shè)置使用采樣一致性方法的類型(用戶給定參數(shù)),采樣一致性方法的類型有
        //SAC_RANSAC(隨機(jī)采樣一致性)、SAC_LMEDS(最小平方中值)、 SAC_MSAC(M估計(jì)采樣一致性)、SAC_RRANSAC(隨機(jī)采樣一致性)、SAC_RMSAC(M估計(jì)采樣一致性)、SAC_MLESAC(最大似然采樣一致性)、SAC_PROSAC(漸進(jìn)一致性采樣)
        sac.setMethodType(methodType);
        //設(shè)置隨機(jī)采樣一致性所構(gòu)造的幾何模型的類型(用戶給定的參數(shù)),model為指定的模型類型參數(shù)SACMODEL_PLANE,SACMODEL_LINE,SACMODEL_CIRCLE2D,SACMODEL_CIRCLE3D,SACMODEL_SPHERE,SACMODEL_CYLINDER,SACMODEL_CONE,SACMODEL_TORUS,SACMODEL_PARALLEL_LINE,SACMODEL_PERPENDICULAR_PLANE,SACMODEL_PARALLEL_LINES,SACMODEL_NORMAL_PLANE,SACMODEL_NORMAL_SPHERE,SACMODEL_REGISTRATION,SACMODEL_REGISTRATION_2D,SACMODEL_PARALLEL_PLANE,SACMODEL_NORMAL_PARALLEL_PLANE,SACMODEL_STICK
        sac.setModelType(modelType);
        //設(shè)置點(diǎn)到模型的距離閾值,如果點(diǎn)到模型的距離不超過這個(gè)距離閾值,認(rèn)為該點(diǎn)為局內(nèi)點(diǎn),否則認(rèn)為是局外點(diǎn),被剔除。
        sac.setDistanceThreshold(distance);
        sac.setMaxIterations(max_iterations);   //設(shè)置迭代次數(shù)的上限
        sac.setProbability(probability);        //設(shè)置每次從數(shù)據(jù)集中選取至少一個(gè)局內(nèi)點(diǎn)的概率
        
        ////設(shè)置是否對(duì)估計(jì)的模型參數(shù)進(jìn)行優(yōu)化
        //sac.setOptimizeCoefficients(optimize); 
        ////該函數(shù)配合,當(dāng)用戶設(shè)定帶有半徑參數(shù)的模型類型時(shí),設(shè)置模型半徑參數(shù)的最大最小半徑閾值
        //sac.setRadiusLimits(min_radius, max_radius);
        ////該函數(shù)配合,當(dāng)用戶設(shè)定與軸線平行或垂直有關(guān)的模型類型時(shí),設(shè)置垂直或平行于所要建立模型的軸線。
        //sac.setAxis(ax);
        ////該函數(shù)配合,當(dāng)用戶設(shè)定有平行或垂直限定有關(guān)的模型類型時(shí),設(shè)置判斷是否平行或垂直時(shí)的角度閾值,ea是最大角度差,采用弧度制。
        //sac.setEpsAngle(ea);
        
        //輸出最終估計(jì)的模型參數(shù),以及分割得到的點(diǎn)集合索引
        sac.segment(cluster_indices_out, coefficients_out);
    }

凸包分割

通過設(shè)置一組處于同一平面模型上的點(diǎn)索引向量,并指定一高度,利用指定的點(diǎn)形成二維凸包,再結(jié)合指定高度一起生成一個(gè)立體多邊形棱柱模型,該類用于分割出該棱柱模型內(nèi)部的點(diǎn)集,比如分割出放在平面上的物體。

#include <pcl/segmentation/extract_polygonal_prism_data.h>
    /// <summary>
    /// 凸包分割
    /// </summary>
    /// <param name="cloud_in">輸入點(diǎn)云</param>
    /// <param name="cluster_indices_out">輸出索引</param>
    /// <param name="hull_in">凸包點(diǎn)云</param>
    /// <param name="height_min">最大高度</param>
    /// <param name="height_max">最小高度</param>
    /// <param name="vpx">視點(diǎn)坐標(biāo)x</param>
    /// <param name="vpy">視點(diǎn)坐標(biāo)x</param>
    /// <param name="vpz">視點(diǎn)坐標(biāo)z</param>
    void extractPolygonalPrismDataExtraction(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr& hull_in, pcl::PointIndices& cluster_indices_out, double height_min, double height_max, float vpx, float vpy, float vpz) {
        pcl::ExtractPolygonalPrismData<pcl::PointXYZ> eppd;
        //設(shè)置高度范圍(height_max為最大高度、height_min為最小高度),當(dāng)給定點(diǎn)云中的點(diǎn)到構(gòu)造棱柱體的平面模型的距離超出指定的這個(gè)高度范圍時(shí),該點(diǎn)視為局外點(diǎn),所有的局外點(diǎn)都會(huì)被剔除。
        eppd.setHeightLimits(height_min, height_max);
        eppd.setViewPoint(vpx, vpy, vpz);       //設(shè)置視點(diǎn),vpx,vpy,vpz分別為視點(diǎn)的三維坐標(biāo)。
        eppd.setInputCloud(cloud_in);
        eppd.setInputPlanarHull(hull_in);       //設(shè)置平面模型上的點(diǎn)集,hull為指向該點(diǎn)集的指針
        eppd.segment(cluster_indices_out);      //從點(diǎn)云中提取聚類,并將點(diǎn)云索引保存在cluster_indices中
    }

其他不常用的

pcl::SeededHueSegmentation是基于顏色信息的點(diǎn)云區(qū)域生長(zhǎng)分割算法,該算法在分割時(shí)不僅使用了點(diǎn)云的空間信息還使用了點(diǎn)云所帶的可見光信息,非常適合對(duì)基于RGBD設(shè)備獲取的點(diǎn)云進(jìn)行分割處理。
pcl::SegmentDifferences可以得到在對(duì)應(yīng)點(diǎn)最大偏差距離限制下的兩個(gè)配準(zhǔn)后點(diǎn)云的差異,此算法輸入為兩組已經(jīng)配準(zhǔn)的點(diǎn)云,設(shè)置兩組點(diǎn)云對(duì)應(yīng)點(diǎn)之間的偏差距離閾值,最后返回兩組點(diǎn)云的差。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容