jakteristics icon indicating copy to clipboard operation
jakteristics copied to clipboard

geodesic graph distance

Open YertleTurtleGit opened this issue 2 years ago • 4 comments

Geodesic Graph Distance

Why?

'Classic' (Euclidean distance) neighborhood search in point clouds has some downsides when it comes to structures that are thin in one dimension and close in proximity to the neighborhood radius (e.g., small twigs in a lidar scan of a tree). When computing geometric features using such a classic neighborhood approach, it is possible for adjacent twigs to interfere with each other in a way that the geometric features do not accurately represent an individual twig.

What?

The method to prevent that was well visualized here: Fig. 4 from the paper: Jiang, Anling, et al. "Skeleton extraction from point clouds of trees with complex branches via graph contraction." The Visual Computer 37 (2021): 2235-2251.

and is also implemented in PyVista for single paths and meshes: Image from: https://docs.pyvista.org/version/stable/examples/01-filter/geodesic.html

How?

The functionality is implemented to ensure backward compatibility. You can still utilize the compute_features method, and if you provide a max_graph_edge_length parameter that is smaller than the search_radius, the new functionality will be activated.

from jakteristics import compute_features

features = compute_features(xyz, search_radius=0.15, max_graph_edge_length=0.05, feature_names=['planarity', 'linearity'])

It will compute the classic neighborhood and filter out any points that cannot be reached with edges, where each individual edge must be smaller or equal to max_graph_edge_length, and the cumulative sum of the edges must be smaller or equal to search_radius.

Results

search_radius=0.5 (both) max_graph_edge_length=0.1 (only for Geodesic distance)

Feature 'Classic' (only Euclidean distance) Geodesic distance
number_of_neighbors number_of_neighbors number_of_neighbors_geodesic
eigenvalue1 eigenvalue eigenvalue1_geodesic
PCA2 pca2 pca2_geodesic

Why not?

  • it's slow
  • it requires more RAM (The best way to reduce RAM usage is to gradually decrease the value of max_k_neighbors. In most cases, this will not affect the result.)
  • you have to decide on two parameters instead of one :smile:

YertleTurtleGit avatar May 23 '23 08:05 YertleTurtleGit

There are still a few optional TODOs remaining, but everything should be functioning properly.

YertleTurtleGit avatar May 23 '23 09:05 YertleTurtleGit

By the way: I think have a basic understanding of Python and C, but if you come across anything that appears unusual in Cython, it is likely because it is indeed strange. Please let me know!

YertleTurtleGit avatar May 23 '23 10:05 YertleTurtleGit

@davidcaron Hey, any updates on that, what do you think?

YertleTurtleGit avatar Jul 11 '23 09:07 YertleTurtleGit

Hey, sorry for the delay.

I think this looks very interesting, thanks for the detailed explanation.

I'll try to find the time to test this soon!

davidcaron avatar Jul 28 '23 21:07 davidcaron