※当サイトはPRを含みます

【Python_3D点群処理】点群のダウンサンプリング:ボクセルグリッドフィルタについての解説と実装

2023年8月30日

はじめに

点群データのダウンサンプリング方法について第二弾です。

こちらの記事でダウンサンプリングの概要とFPS(Farthest point sampling)の解説をしていますのでぜひご覧ください。

今回はボクセルグリットフィルターについての解説とPythonでの実装をしていきます。

そもそもボクセルとは?

ボクセル(voxel)とは体積(volume)とピクセル(pixel)を組み合わせた言葉で、立体物の表現に用いられる小さな立方体の最小単位であり、二次元画像におけるピクセルに相当します。

このボクセルを組み合わせることで物体を立体的に表現することができます。

ボクセルグリッドフィルタとは

本題のボクセルグリッドフィルタに戻ります。

ボクセルグリッドフィルタは、立方体のグリッドを配置し、そのグリッド内の点の重心を求めて1点に置き換えることで点の数を減らします。

したがってグリッドの大きさを変えることでサンプリング数を変更することができます。グリッドを2つ配置すると以下のようなサンプリングすることができます。

Pythonでの実装

ボクセルグリッドフィルタはOpen3Dですでに用意されているのでそちらを利用します。

コードは以下のようになります。

import numpy as np
import open3d as o3d

# 点群の読み込み
bunny = np.loadtxt('/bunny.txt')

# Open3dで取り扱えるようにnumpy配列を変換
points=o3d.utility.Vector3dVector(bunny)
pcd=o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points)

# ボクセルグリッドフィルタ(Open3D)
downpcd_voxel=pcd.voxel_down_sample(voxel_size=0.00818)
bunny_voxel=np.asarray(downpcd_voxel.points)

はじめに点群を読み込んで、Open3dで取り扱えるようにnumpy配列を変換します。

今回使用した点群のサンプル数は30571点なので1000点程度にダウンサンプリングしてみます。

ボクセルサイズを0.00818に設定してダウンサンプリングを実施した結果が以下の画像です。

点数は1018点となりました。グリッドを配置してその中の重心点を取るようにしているので、規則正しくサンプリングされています。

また、今回はランダムサンプリングとFPSも使用して1000点程度にダウンサンプリングしてみました。

# ランダムサンプリング(Open3D)
downpcd_random=pcd.uniform_down_sample(every_k_points=30)
bunny_random=np.asarray(downpcd_random.points)

# FPS
bunny_fps=farthest_point_sample(bunny,len(bunny)//30)

実行結果は以下のようになりました。

見た目の感想です。

ランダムサンプリング:抜け落ちている箇所もあり、まばらにサンプリングされている。

FPS:遠い点からサンプリングする手法なので輪郭がはっきりとなるようにサンプリングされている。

ボクセルグリッドフィルタ:均等にサンプリングされていて形状もわかりやすい。

おすすめ参考書