isl-org / Open3D

Open3D: A Modern Library for 3D Data Processing
http://www.open3d.org
Other
10.82k stars 2.24k forks source link

search_radius_vector_3d crashes when using a kdtree retured by a function #5012

Open JensOle100 opened 2 years ago

JensOle100 commented 2 years ago

Checklist

Describe the issue

I've been writing code to find the intersection of a line and a pointcloud. For this I iterate over the line segment and do a search_radius_vector_3d at each point on the line. This resulted in the code just stopping. No return, no error, it just ends.

The problem occurs when building the kdtree inside a function and returning it. This causes the search_radius_vector_3d to only return something in 10% of the times it ran, and just crash without any error or return in 90% of the times it ran.

When building the kdtree directly without any functions it works 100% of the time.

Steps to reproduce the bug

import open3d as o3d
import numpy as np

#### Works 100% of the time ####
pcd = o3d.io.read_point_cloud('Databases/Pointclouds/nissan.ply')
downpcd = pcd.voxel_down_sample(voxel_size = 10)
kdtree = o3d.geometry.KDTreeFlann(downpcd)

point = np.array([0,500,100] , dtype = np.float64)
result = kdtree.search_hybrid_vector_3d(point, 48, 1)
print(result)

#### Works 10% of the time ####
def import_pointcloud(filepath, detail):
    pcd = o3d.io.read_point_cloud(filepath)
    downpcd = pcd.voxel_down_sample(voxel_size = detail)
    kdtree = o3d.geometry.KDTreeFlann(downpcd)

    return kdtree

kdtree = import_pointcloud('Databases/Pointclouds/nissan.ply', 10)

point = np.array([0,500,100] , dtype = np.float64)
result = kdtree.search_hybrid_vector_3d(point, 48, 1)
print(result)

Error message

No error message at all.

Expected behavior

No response

Open3D, Python and System information

- Operating system: Windows 11 64-bit
- Python version: 3.9.7 (tags/v3.9.7:1016ef3, Aug 30 2021, 20:19:38) [MSC v.1929 64 bit (AMD64)]
- Open3D version: 0.15.1
- System architecture: 64 bit (AMD64)
- Is this a remote workstation?: no
- How did you install Open3D?: pip

Additional information

No response

hernot commented 2 years ago

I do encounter a similar problem in 1.15.2. Instead of passing a point cloud i pass a numpy array. appart from having to pass the list of points as [3 n] array instead of [n 3] as for o3d.utility.Vector3dVector and alike interfaces i do obeserve that at least the python interfaces drops most of the time or partially the data passed to KDTreeFlann construtor as well as to KDTreeFlann.set_matrix_data. It thereby does not matter whether i pass a numpy.ndarray_view or a fresh numpy.ndarray copy of my data. The only thing which works stable is to create a fresh o3d.geometry.PointCloud and assign to PointCloud.points an o3d.utility.Vector3dVector copy of my data. Passing this point cloud works stable. Passing the numpy.ndarray_view works worst most time it is a guessing game. The fresh numpy.ndarray is a bit less guessing game but not much better.

I guess there are two issues here 1 the KDTreeFlann can not properly cope with view slices of data independent whether numpy or Vector3DVector. It tries to pass the data directly than creating an intermediate open3d.utility.Vector3DVector before passing to nanoflann. And finally instead of forcing callers to care about provding proper data shape it would be better to remodel the interface to be consistent with open3d.utility.Vector3dVector interface and have KDTreeFlann explicitly remap to [3 n] layout than hoping that caller will pass in data in the expected format beeing contigous in rows and jump in columns (guess nanoflann assumes fortran contiguoity) while numpy and open3d have c-contiguoity so even transposing does not help in worst. As transposing typically at least in numpy just creates a new view/new array swapping the axis order but not moving the data.

hernot commented 1 year ago

Update: calling ndarray.copy before passing the proper shaped ndarray seems to be a suitable workaround. If that also is of any value for the problem reported by @JensOle100, i do have no idea. And only tested with ndarray[M=6,N] representing 3D-Points+Point normals not with ndarray[M=3,N] representing 3D points on.