generated from HiraiKyo/pyproject-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from HiraiKyo/feature/clustering
平面上の点群のDBSCANクラスタリング実装
- Loading branch information
Showing
5 changed files
with
72 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import numpy as np | ||
from numpy.typing import NDArray | ||
from sklearn.cluster import DBSCAN | ||
|
||
|
||
def plane_clustering(points: NDArray[np.floating], eps: float = 1.0, min_samples: int = 100): | ||
""" | ||
DBSCANによる平面上の点群のクラスタリングを行う | ||
:param points: 平面上の点群(N, 2) | ||
:return: クラスタ点数の多い順にソートされたクラスタ点群ポインタ(N, M) | ||
""" | ||
dbscan = DBSCAN(eps=eps, min_samples=min_samples, metric="euclidean") | ||
clusters = dbscan.fit_predict(points[:, :2]) | ||
unique_clusters, counts = np.unique(clusters, return_counts=True) | ||
# クラスタリングできなかった点群(-1)は除外 | ||
unique_clusters = unique_clusters[unique_clusters != -1] | ||
# 各クラスタの点群ポインタを返す | ||
cluster_indices = [np.where(clusters == cluster)[0] for cluster in unique_clusters] | ||
return cluster_indices |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import numpy as np | ||
import open3d as o3d | ||
import pytest | ||
|
||
from ply_processor_basics.points import plane_clustering | ||
from ply_processor_basics.points.ransac import detect_plane | ||
|
||
|
||
@pytest.mark.parametrize("plypath", ["data/samples/sample_clustering.ply"]) | ||
def test_success(plypath): | ||
pcd = o3d.io.read_point_cloud(plypath) | ||
points = np.asarray(pcd.points) | ||
|
||
inliers, plane_model = detect_plane(points, threshold=1.0) | ||
# EPS=10.0でサンプルデータ点群のクラスタリングが正常動作した事を確認 | ||
clusters_indices = plane_clustering(points[inliers], eps=10.0) | ||
# クラスタが2つ認識されることを期待 | ||
assert len(clusters_indices) == 2 | ||
|
||
|
||
@pytest.mark.parametrize("plypath", ["data/samples/sample_clustering.ply"]) | ||
@pytest.mark.visual | ||
def test_visualize(plypath): | ||
pcd = o3d.io.read_point_cloud(plypath) | ||
points = np.asarray(pcd.points) | ||
|
||
inliers, plane_model = detect_plane(points, threshold=1.0) | ||
# サンプルデータはZ軸方向に平面の法線が存在するので座標変換は行わない | ||
clusters_indices = plane_clustering(points[inliers], eps=10.0) # EPS=10.0mmくらいで適切な | ||
pcds = [] | ||
for cluster in clusters_indices: | ||
pcd = o3d.geometry.PointCloud() | ||
pcd.points = o3d.utility.Vector3dVector(points[inliers][cluster]) | ||
pcd.paint_uniform_color([np.random.rand(), np.random.rand(), np.random.rand()]) | ||
pcds.append(pcd) | ||
o3d.visualization.draw_geometries(pcds) |