2015年05月25日

PCL 1.7.2のOctreeのテスト

Voxelで何かしようかなと思っているのですが、高速化のためにはOctreeなどデータ構造が大事かと思いますので、Point Cloud LibraryのOctreeを使用することにしました。本当はSparse Voxel Octreeのライブラリなどを使用した方がいいのだとは思いますので、機会があれば試してみたいと思います。

PCL 1.7.2の導入
公式は1.6.0のall-in-one-installersしかなかったですが、[1]で1.7.2のものを公開していただいていましたので、そちらを使用させていただきました。octreeのtutorialsは[2]にあります。今回必要なのはoctreeだけなので、includeやlibも最低限必要なものだけにしておきます。

インクルードのパス
$(PCL_ROOT)\include\pcl-1.7;
$(PCL_ROOT)\3rdParty\Eigen\Eigen3;
$(PCL_ROOT)\3rdParty\Boost\include\boost-1_57;

ライブラリのパス
$(PCL_ROOT)\lib;

ライブラリ(リリース)
pcl_octree_release.lib;

実行時に必要なライブラリ
$(PCL_ROOT)\bin\pcl_octree_release.dll

[3]を参考に、MagicaVoxelのVoxデータを読み込んでRaycastingで表示してみました。

ソースの一部(画像処理・レイの計算部分は省略)
#include <pcl/point_cloud.h>
#include <pcl/octree/octree.h>

int rayCastTest(const int width, const int height)
{
    int hit = 0;

    MV_Model mv;
    mv.LoadModel("voxel/doom.vox");

    // ポイントクラウドの作成(色情報のためのラベルのためPointXYZLを使用)
    pcl::PointCloud<pcl::PointXYZL>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZL>);

    // 画像とレイキャスティングの準備は省略

    // voxデータからポイントクラウドを生成
    cloud->width = mv.voxels.size();
    cloud->height = 1;
    cloud->points.resize (cloud->width * cloud->height);

    for (size_t i = 0; i < cloud->points.size (); ++i)
    {
        cloud->points[i].x = mv.voxels[i].x;
        cloud->points[i].y = mv.voxels[i].y;
        cloud->points[i].z = mv.voxels[i].z;
        cloud->points[i].label = mv.voxels[i].colorIndex;
    }

    // octreeの生成、解像度はoctreeのボクセルのサイズ?
    float resolution = 1.0f;
    pcl::octree::OctreePointCloudSearch<pcl::PointXYZL> octree (resolution);

    octree.setInputCloud (cloud);
    octree.addPointsFromInputCloud ();

    // レイとボクセルの衝突判定
    std::vector<int> k_indices;

    Eigen::Vector3f org, target, dir;
    for (int y=0; y<height; y++)
    {
        for (int x=0; x<width; x++)
        {
            // 画素からレイの到達先を計算
            // 視点位置と到達先からレイの方向を計算

            // octreeとvoxelの衝突判定(1回)
            int ret = octree.getIntersectedVoxelIndices(org, dir, k_indices, 1);
            if (ret > 0)
            {
                // 今回は1個目のindex固定(解像度によってはk_indicesが複数Indexを含む)
                int label = cloud->points[k_indices[0]].label;
                // パレットから色を取得して画像に設定
                color.r = mv.palette[label].r;
                color.g = mv.palette[label].g;
                color.b = mv.palette[label].b;
                hit++;
            }
        }
    }
    // 画像の保存
    return hit;
}
実行結果(MagicaVoxel付属のサンプルdoom.vox使用)
pcl_test_001.png
ボクセル数2万弱、1024x1024の画像で、レイキャスティングの時間だけで400msぐらいでした。どちらかというと、全部のレイと衝突判定するのではなく、全部のボクセルを枝刈りしながらレイに当たるか判定する陰面消去的な探索がしたいのですが、どうやるんですかね。

[1] http://unanancyowen.com/?p=712
[2] http://pointclouds.org/documentation/tutorials/#octree-tutorial
[3] http://voxel.codeplex.com/wikipage?title=Sample%20Codes
posted by シンドラー at 00:56 | Comment(0) | TrackBack(0) | Image Processing | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバック