2015年2月24日火曜日

センサから取得された点郡の不要データを除去するフィルタ

 Kinectなどのセンサは通常307200個の点郡が取れるはずであるが、あくまでも赤外線を照射して帰ってきた情報しか取得できないため、ガラスなどの点郡はとることができない。しかし、一応データは存在するものとして扱われる(QNANのような感じになり、Viewerなどでは表示されない)そういったデータは処理の邪魔でしかないので消去するべきなのでPCLではPassThroughフィルタというものがあるのでそれを使用することで消去できる。以下入力された点郡データの使用できないデータを消去するコード。

コード

#include "stdafx.h"

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/io/pcd_io.h>


pcl::PointCloud<pcl::PointXYZ>::Ptr pass_through(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PassThrough<pcl::PointXYZ> pass;
    pass.setInputCloud (cloud);
    pass.setFilterFieldName ("z");
    pass.setFilterLimits (0, 10);
    //pass.setFilterLimitsNegative (true);
    pass.filter (*cloud_filtered);
    printf("%f\n",cloud->points.size());

    return cloud_filtered;
}

int _tmain(int argc, _TCHAR* argv[])
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
   
    pcl::io::loadPCDFile(argv[1], *cloud);
    //pass_through(cloud);

    std::stringstream Filename;
    std::string name;
    name = argv[1];
    name.erase(name.length()-4);
    Filename << name << "_pass.pcd";

    pcl::io::savePCDFileBinary(Filename.str() , *pass_through(cloud));

    return (0); 
}


 このフィルタは通常は表示するデータのX、Y、Zの値を元にして、閾値以上となった場合は表示しないなどの処理を行うものであるが、今回のように「存在しない」という情報を持つ点の削除を行うこともできる。 以下Z座標値が0~0.05の場合のみ表示するコード。

コード

#include "stdafx.h"

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/io/pcd_io.h>


 pcl::PointCloud<pcl::PointXYZ>::Ptr pass_through(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PassThrough<pcl::PointXYZ> pass;
    pass.setInputCloud (cloud);
    pass.setFilterFieldName ("z");
    pass.setFilterLimits (0, 0.05);
    //pass.setFilterLimitsNegative (true);
    pass.filter (*cloud_filtered);
    printf("%f\n",cloud->points.size());

    return cloud_filtered;
}

int _tmain(int argc, _TCHAR* argv[])
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
   

    pcl::io::loadPCDFile(argv[1], *cloud);
    //pass_through(cloud);

   std::stringstream Filename;
    std::string name;
    name = argv[1];
    name.erase(name.length()-4);
    Filename << name << "_pass.pcd";

    pcl::io::savePCDFileBinary(Filename.str() , *pass_through(cloud));

    return (0); 
}

 

 このコードの実行結果
 

 斜体+下線+太字の部分の値を変えただけ、ものは全く同じ。
このフィルタを使えば表示する点郡の数を減らせるので処理を速くできる。(有用不要にかかわらず情報の削除を行うので注意は必要)

0 件のコメント:

コメントを投稿