Open3Dの使い方:FPFH特徴でレジストレーション

More than 1 year has passed since last update.

pythonで点群処理できるOpen3Dの探検.

点群特徴FPFHで位置合わせして,ICPで微修正.

- 公式チュートリアルを見やすくしてみた.

- 数値がハードコードだったので,点群のサイズの1/10を基本にして,他のいろいろなパラメータを決めるようにしてみた.

- メソッド名が長いので,import asで短く

Tips:

- ダウンサンプリングのサイズを1/10程度に粗くしないと,RANSACがうまく機能しない.(1/100ぐらい細かくしすぎるとダメ)

- FPFHのサイズは1/10 * 50にしている.大きめのほうが良さそう.(小さすぎると特徴計算に使う点の数が少なくなるから)

- 法線計算は1/10にしているが,あまり影響なし.


コード


open3d

import sys

sys.path.append("../..") # Open3D/build/lib/ へのパス
import copy
import numpy as np
import py3d
from py3d import registration_ransac_based_on_feature_matching as RANSAC
from py3d import registration_icp as ICP
from py3d import compute_fpfh_feature as FPFH

def show(model, scene, model_to_scene_trans=np.identity(4)):
model_t = copy.deepcopy(model)
scene_t = copy.deepcopy(scene)

model_t.paint_uniform_color([1, 0, 0])
scene_t.paint_uniform_color([0, 0, 1])

model_t.transform(model_to_scene_trans)

py3d.draw_geometries([model_t, scene_t])

model = py3d.read_point_cloud("bun000.ply")
scene = py3d.read_point_cloud("bun045.ply")
## PCLモデルを使うならこちら
#model = py3d.read_point_cloud("milk.pcd")
#scene = py3d.read_point_cloud("milk_cartoon_all_small_clorox.pcd")

# いろいろなサイズの元: model点群の1/10を基本サイズsizeにする
size = np.abs((model.get_max_bound() - model.get_min_bound())).max() / 10
kdt_n = py3d.KDTreeSearchParamHybrid(radius=size, max_nn=50)
kdt_f = py3d.KDTreeSearchParamHybrid(radius=size * 50, max_nn=50)

py3d.estimate_normals(model, kdt_n)
py3d.estimate_normals(scene, kdt_n)
show(model, scene)

# ダウンサンプリング
model_d = py3d.voxel_down_sample(model, size)
scene_d = py3d.voxel_down_sample(scene, size)
py3d.estimate_normals(model_d, kdt_n)
py3d.estimate_normals(scene_d, kdt_n)
show(model_d, scene_d)

# 特徴量計算
model_f = FPFH(model_d, kdt_f)
scene_f = FPFH(scene_d, kdt_f)

# 準備
checker = [py3d.CorrespondenceCheckerBasedOnEdgeLength(0.9),
py3d.CorrespondenceCheckerBasedOnDistance(size * 2)]

est_ptp = py3d.TransformationEstimationPointToPoint()
est_ptpln = py3d.TransformationEstimationPointToPlane()

criteria = py3d.RANSACConvergenceCriteria(max_iteration=40000,
max_validation=500)
# RANSACマッチング
result1 = RANSAC(model_d, scene_d,
model_f, scene_f,
max_correspondence_distance=size * 2,
estimation_method=est_ptp,
ransac_n=4,
checkers=checker,
criteria=criteria)
show(model_d, scene_d, result1.transformation)

# ICPで微修正
result2 = ICP(model, scene, size, result1.transformation, est_ptpln)
show(model, scene, result2.transformation)



結果

以下の結果はサイズが1/30のときのもの.(1/10にするともっと粗くなる)


bunny

元の点群

スクリーンショット 2018-03-26 16.02.28.png

ダウンサンプリング後

スクリーンショット 2018-03-26 16.02.33.png

RANSACマッチング後

スクリーンショット 2018-03-26 16.02.38.png

ICP後

スクリーンショット 2018-03-26 16.02.43.png


PCLのデーブル・ミルクデータ

元の点群

スクリーンショット 2018-03-26 16.01.20.png

ダウンサンプリング後

スクリーンショット 2018-03-26 16.01.30.png

RANSACマッチング後

スクリーンショット 2018-03-26 16.01.50.png

ICP後

スクリーンショット 2018-03-26 16.02.02.png