{"id":25431937,"url":"https://github.com/drprojects/point_geometric_features","last_synced_at":"2025-04-05T06:10:41.209Z","repository":{"id":65530649,"uuid":"567493677","full_name":"drprojects/point_geometric_features","owner":"drprojects","description":"Python wrapper around C++ utilities for computing neighbors and local geometric features of a point cloud","archived":false,"fork":false,"pushed_at":"2025-02-18T08:41:10.000Z","size":113,"stargazers_count":62,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-29T05:06:42.479Z","etag":null,"topics":["3d","cpu","fast","features","geometric-features","machine-learning","nanoflann","nearest-neighbors","neighbor-search","numpy","point-cloud","python","radius-neighbors"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/drprojects.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-17T22:56:44.000Z","updated_at":"2025-02-24T03:56:09.000Z","dependencies_parsed_at":"2024-03-19T16:49:33.301Z","dependency_job_id":"a21e82ce-658b-4870-8247-9a2e082f3e4a","html_url":"https://github.com/drprojects/point_geometric_features","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drprojects%2Fpoint_geometric_features","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drprojects%2Fpoint_geometric_features/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drprojects%2Fpoint_geometric_features/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drprojects%2Fpoint_geometric_features/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drprojects","download_url":"https://codeload.github.com/drprojects/point_geometric_features/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247294541,"owners_count":20915340,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d","cpu","fast","features","geometric-features","machine-learning","nanoflann","nearest-neighbors","neighbor-search","numpy","point-cloud","python","radius-neighbors"],"created_at":"2025-02-17T04:30:34.480Z","updated_at":"2025-04-05T06:10:41.187Z","avatar_url":"https://github.com/drprojects.png","language":"C++","readme":"\u003cdiv align=\"center\"\u003e\n\n# Point Geometric Features\n\n[![python](https://img.shields.io/badge/-Python_3.9_%7C_3.10_%7C_3.11_%7C_3.12-blue?logo=python\u0026logoColor=white)](#)\n![C++](https://img.shields.io/badge/c++-%2300599C.svg?style=for-the-badge\u0026logo=c%2B%2B\u0026logoColor=white)\n[![license](https://img.shields.io/badge/License-MIT-green.svg?labelColor=gray)](#)\n\n\n\u003c/div\u003e\n\n\n## 📌 Description\n\nThe `pgeof` library provides utilities for fast, parallelized computing ⚡ of **local geometric \nfeatures for 3D point clouds** ☁️ **on CPU** .\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e️List of available features ️👇\u003c/b\u003e\u003c/summary\u003e\n\n- linearity\n- planarity\n- scattering\n- verticality (two formulations)\n- normal_x\n- normal_y\n- normal_z\n- length\n- surface\n- volume\n- curvature\n- optimal neighborhood size\n\u003c/details\u003e\n\n`pgeof` allows computing features in multiple fashions: **on-the-fly subset of features** \n_a la_ [jakteristics](https://jakteristics.readthedocs.io), **array of features**, or \n**multiscale features**. Moreover, `pgeof` also offers functions for fast **K-NN** or \n**radius-NN** searches 🔍. \n\nBehind the scenes, the library is a Python wrapper around C++ utilities.\nThe overall code is not intended to be DRY nor generic, it aims at providing efficient as \npossible implementations for some limited scopes and usages.\n\n## 🧱 Installation\n\n### From binaries\n\n```bash\npython -m pip install pgeof \n```\n\nor \n\n```bash\npython -m pip install git+https://github.com/drprojects/point_geometric_features\n```\n\n### Building from sources\n\n`pgeof` depends on [Eigen library](https://eigen.tuxfamily.org/), [Taskflow](https://github.com/taskflow/taskflow), [nanoflann](https://github.com/jlblancoc/nanoflann) and [nanobind](https://github.com/wjakob/nanobind).\nThe library adheres to [PEP 517](https://peps.python.org/pep-0517/) and uses [scikit-build-core](https://github.com/scikit-build/scikit-build-core) as build backend. \nBuild dependencies (`nanobind`, `scikit-build-core`, ...) are fetched at build time.\nC++ third party libraries are embedded as submodules.\n\n\n```bash\n# Clone project\ngit clone --recurse-submodules https://github.com/drprojects/point_geometric_features.git\ncd point_geometric_features\n\n# Build and install the package\npython -m pip install .\n```\n\n## 🚀 Using Point Geometric Features\n\nHere we summarize the very basics of `pgeof` usage. \nUsers are invited to use `help(pgeof)` for further details on parameters.\n\nAt its core `pgeof` provides three functions to compute a set of features given a 3D point cloud and\nsome precomputed neighborhoods.\n\n```python\nimport pgeof\n\n# Compute a set of 11 predefined features per points\npgeof.compute_features(\n    xyz, # The point cloud. A numpy array of shape (n, 3)\n    nn, # CSR data structure see below\n    nn_ptr, # CSR data structure see below\n    k_min = 1 # Minimum number of neighbors to consider for features computation\n    verbose = false # Basic verbose output, for debug purposes\n)\n```\n\n```python\n# Sequence of n scales feature computation\npgeof.compute_features_multiscale(\n    ...\n    k_scale # array of neighborhood size\n)\n```\n\n```python\n# Feature computation with optimal neighborhood selection as exposed in Weinmann et al., 2015\n# return a set of 12 features per points (11 + the optimal neighborhood size)\npgeof.compute_features_optimal(\n    ...\n    k_min = 1, # Minimum number of neighbors to consider for features computation\n    k_step = 1, # Step size to take when searching for the optimal neighborhood\n    k_min_search = 1, # Starting size for searching the optimal neighborhood size. Should be \u003e= k_min \n)\n```\n\n⚠️ Please note that for theses three functions the **neighbors are expected in CSR format**. \nThis allows expressing neighborhoods of varying sizes with dense arrays (e.g. the output of a \nradius search).\n\nWe provide very tiny and specialized **k-NN** and **radius-NN** search routines. \nThey rely on `nanoflann` C++ library and should be **faster and lighter than `scipy` and \n`sklearn` alternatives**.\n\nHere are some examples of how to easily compute and convert typical k-NN or radius-NN neighborhoods to CSR format (`nn` and `nn_ptr` are two flat `uint32` arrays):\n\n```python\nimport pgeof\nimport numpy as np\n\n# Generate a random synthetic point cloud and k-nearest neighbors\nnum_points = 10000\nk = 20\nxyz = np.random.rand(num_points, 3).astype(\"float32\")\nknn, _ = pgeof.knn_search(xyz, xyz, k)\n\n# Converting k-nearest neighbors to CSR format\nnn_ptr = np.arange(num_points + 1) * k\nnn = knn.flatten()\n\n# You may need to convert nn/nn_ptr to uint32 arrays\nnn_ptr = nn_ptr.astype(\"uint32\")\nnn = nn.astype(\"uint32\")\n\nfeatures = pgeof.compute_features(xyz, nn, nn_ptr)\n```\n\n```python\nimport pgeof\nimport numpy as np\n\n# Generate a random synthetic point cloud and k-nearest neighbors\nnum_points = 10000\nradius = 0.2\nk = 20\nxyz = np.random.rand(num_points, 3).astype(\"float32\")\nknn, _ = pgeof.radius_search(xyz, xyz, radius, k)\n\n# Converting radius neighbors to CSR format\nnn_ptr = np.r_[0, (knn \u003e= 0).sum(axis=1).cumsum()]\nnn = knn[knn \u003e= 0]\n\n# You may need to convert nn/nn_ptr to uint32 arrays\nnn_ptr = nn_ptr.astype(\"uint32\")\nnn = nn.astype(\"uint32\")\n\nfeatures = pgeof.compute_features(xyz, nn, nn_ptr)\n```\n\nAt last, and as a by-product, we also provide a function to **compute a subset of features on the fly**. \nIt is inspired by the [jakteristics](https://jakteristics.readthedocs.io) python package (while \nbeing less complete but faster).\nThe list of features to compute is given as an array of `EFeatureID`.\n\n```python\nimport pgeof\nfrom pgeof import EFeatureID\nimport numpy as np\n\n# Generate a random synthetic point cloud and k-nearest neighbors\nnum_points = 10000\nradius = 0.2\nk = 20\nxyz = np.random.rand(num_points, 3)\n\n# Compute verticality and curvature\nfeatures = pgeof.compute_features_selected(xyz, radius, k, [EFeatureID.Verticality, EFeatureID.Curvature])\n```\n\n## Known limitations\n\nSome functions only accept `float` scalar types and `uint32` index types, and we avoid implicit\ncast / conversions.\nThis could be a limitation in some situations (e.g. point clouds with `double` coordinates or \ninvolving very large big integer indices).\nSome C++ functions could be templated / to accept other types without conversion.\nFor now, this feature is not enabled everywhere, to reduce compilation time and enhance code \nreadability. \nPlease let us know if you need this feature !\n\nBy convention, our normal vectors are forced to be oriented towards positive Z values. \nWe make this design choice in order to return consistently-oriented normals. \n\n## Testing\n\nSome basic tests and benchmarks are provided in the `tests` directory.\nTests can be run in a clean and reproducible environments via `tox` (`tox run` and\n`tox run -e bench`).\n\n## 💳 Credits\nThis implementation was largely inspired from [Superpoint Graph](https://github.com/loicland/superpoint_graph). The main modifications here allow: \n- parallel computation on all points' local neighborhoods, with neighborhoods of varying sizes\n- more geometric features\n- optimal neighborhood search from this [paper](http://lareg.ensg.eu/labos/matis/pdf/articles_revues/2015/isprs_wjhm_15.pdf)\n- some corrections on geometric features computation\n\nSome heavy refactoring (port to nanobind, test, benchmarks), packaging, speed optimization, feature addition (NN search, on the fly feature computation...) were funded by:\n\nCentre of Wildfire Research of Swansea University (UK) in collaboration with the Research Institute of Biodiversity (CSIC, Spain) and the Department of Mining Exploitation of the University of Oviedo (Spain).\n\nFunding provided by the UK NERC project (NE/T001194/1):\n\n'Advancing 3D Fuel Mapping for Wildfire Behaviour and Risk Mitigation Modelling'\n\nand by the Spanish Knowledge Generation project (PID2021-126790NB-I00):\n\n‘Advancing carbon emission estimations from wildfires applying artificial intelligence to 3D terrestrial point clouds’.\n\n## License\n\nPoint Geometric Features is licensed under the MIT License. \n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrprojects%2Fpoint_geometric_features","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrprojects%2Fpoint_geometric_features","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrprojects%2Fpoint_geometric_features/lists"}