LoginSignup
22
23

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-03-26

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

22
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
23