2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PythonでOpen3Dを使って点群データを一通り遊んでみてキャッキャッする

Posted at

点群データが熱い

これからはセンサーの時代です!(?)
ということでPythonでOpen3Dで遊んでみます。

本当にこの Open3D というライブラリすごいです。
こういうのを作り公開されてくださる方々に心から感謝します……。

Open3Dを使って手持ちの点群で遊んでみる

ライブラリの準備

ライブラリ(Open3D)をインストールする。

> pip install open3d

データの準備

今回用意したのははシンプルな通称 .xyz 形式のファイルです。
X Y Z が並んでいるだけです。

0.365193 0.609847 0.426132
0.320558 0.615929 0.409627
0.171359 0.759521 0.636285
    :

最初の一歩で何も考えずに動かしてみる

最小サンプルを動かして確認してみます!

import open3d as o3d

pcd = o3d.io.read_point_cloud("vase.xyz")
print(pcd)

o3d.visualization.draw_geometries([pcd])

これだけで点群が3D表示されて楽しい!
マウスで画面をぐりぐりできて、Ctrl押しながらで平行移動、Shiftおしながらで回転。Escで終了。

image.png

クラスタリングとかしてみる

少し欲が出てきたからクラスタリング(点の集まりを見つける)してみる。
上手くできない場合は eps と min_points の値をいじると良いです。

import open3d as o3d
import numpy as np
import random

pcd = o3d.io.read_point_cloud("test.xyz")
print(pcd)

with o3d.utility.VerbosityContextManager(o3d.utility.VerbosityLevel.Debug) as cm:
    labels = np.array( pcd.cluster_dbscan(eps=0.7, min_points=5, print_progress=True))
print(labels)

max_label = labels.max()
print(f"point cloud has {max_label + 1} clusters")

colors_array = []
for i in range(max_label+1):
    colors_array.append((random.random(),random.random(),random.random()))

colors = []
for i in range(len(labels)):
    if labels[i]==-1:
        colors.append((0.9,0.9,0.9))
    else:
        colors.append(colors_array[labels[i]])
colors = np.array(colors)

pcd.colors = o3d.utility.Vector3dVector(colors)

o3d.visualization.draw_geometries([pcd])

花瓶の中の何かがクラスタリングされて浮き出て色がかわっています!

image.png

面を割り出してみる

点群だけだと面白くないから面を見つけたい。
そのために法線(面に対して垂直にのびる線)を見つける。

コードを実行したら黒い線がちゃんと面の法線方向に向いてますか?

import open3d as o3d
import numpy as np
import random

pcd = o3d.io.read_point_cloud("vase.xyz")
print(pcd)

size = np.abs((pcd.get_max_bound() - pcd.get_min_bound())).max() / 10
pcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=size, max_nn=50))

o3d.visualization.draw_geometries([pcd],point_show_normal=True)

わあ、、、ちょっと気持ち悪い、、、
でもちゃんと法線を見つけてくれています。

image.png

法線が見つかったら面を作る。

import open3d as o3d
import numpy as np
import random

pcd = o3d.io.read_point_cloud("vase.xyz")
print(pcd)

size = np.abs((pcd.get_max_bound() - pcd.get_min_bound())).max() / 10
pcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=size, max_nn=50))

oboxes = pcd.detect_planar_patches(
    normal_variance_threshold_deg=60,
    coplanarity_deg=75,
    outlier_ratio=0.75,
    min_plane_edge_length=0,
    min_num_points=0,
    search_param=o3d.geometry.KDTreeSearchParamKNN(knn=100))

print("Detected {} patches".format(len(oboxes)))

geometries = []
for obox in oboxes:
    mesh = o3d.geometry.TriangleMesh.create_from_oriented_bounding_box(obox, scale=[1, 1, 0.0001])
    mesh.paint_uniform_color(obox.color)
    geometries.append(mesh)
    geometries.append(obox)
geometries.append(pcd)

o3d.visualization.draw_geometries(geometries)

そりゃあ局面の物体から面を作ったらこうなりますよね、、、

image.png

メッシュを作ってみる

面ではなくメッシュ(いわゆるポリゴン)を割り出してみます。

import open3d as o3d
import numpy as np

pcd = o3d.io.read_point_cloud("vase.xyz")
print(pcd)

size = np.abs((pcd.get_max_bound() - pcd.get_min_bound())).max() / 10
pcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=size, max_nn=50))

pcd.orient_normals_consistent_tangent_plane(10)

distances = pcd.compute_nearest_neighbor_distance()
avg_dist = np.mean(distances)
radius = 2*avg_dist   
radii = [radius, radius * 2]
recMeshBPA = o3d.geometry.TriangleMesh.create_from_point_cloud_ball_pivoting(pcd, o3d.utility.DoubleVector(radii))
    
o3d.visualization.draw_geometries([recMeshBPA])

すごい……。

image.png

ひと通り遊んでみました!

簡単です。
スゴイです。

手元では手持ちのセンサーでとったデータを使っていたのでノイズもあったり等こんなチュートリアルみたいに簡単にはいきませんが、そういうの込みでこれからが熱い界隈だと感じました!!

2
4
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
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?