Library / SDK
leomariga/pyRANSAC-3D avatar
leomariga/pyRANSAC-3D

pyRANSAC-3D: fitting planes, cylinders and cuboids to point clouds

Python library for fitting 3D primitive shapes to point clouds with RANSAC. Detect planes, spheres, cylinders, cuboids, circles, and lines.

669 stars80 forksPythonApache-2.0

At a glance

What is it?
pyRANSAC-3D is a Python implementation of RANSAC that fits eight families of primitive shape to a NumPy point cloud, with only NumPy as a required dependency and Open3D reserved for visualisation. The library targets LiDAR and depth-sensor work in SLAM and reconstruction, where a plane or a cylinder has to be pulled out of noisy data quickly.
Who is it for?
pyRANSAC-3D fits a robotics or computer vision team working with LiDAR or depth-camera point clouds that needs shape hypotheses, inliers and a threshold they control, in plain Python with a single dependency. It does not fit a team that wants a full reconstruction pipeline, since it returns shape parameters rather than a mesh or a map, and it does not fit a project that already has a C++ Open3D pipeline where the extra Python hop is unwelcome.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 56 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Eight shape families, one consistent fit interface

pyRANSAC-3D is described as an open source Python implementation of the Random Sample Consensus method, fitting primitive shapes such as planes, cuboids and cylinders to point clouds for applications including 3D SLAM, 3D reconstruction and object tracking. The README lists the supported shapes as a menu of API documentation pages: Plane, Cylinder, Cone, Cuboid, Sphere, Line, Circle and Point. Each of these is a class you instantiate, and each exposes a fit method with the same shape of return, so the pipeline code that consumes a plane result can be reused for a cylinder result. That consistency is the library's practical value. The audience is a developer who has a point cloud and needs a geometric hypothesis from it, and the project description says exactly that, a Python tool for fitting primitives 3D shapes in point clouds using the RANSAC algorithm. The package is Apache-2.0 licensed and the homepage is leomariga.github.io/pyRANSAC-3D/.

A single dependency, and NumPy arrays as the contract

The installation requirement is NumPy and nothing else.

sh
pip install pyransac3d

The project metadata confirms it, with dependencies = ["numpy"] and a requires-python of >=3.10, and the distribution name on PyPI is pyransac3d while the import name is pyransac3d. The input contract is a NumPy array with shape (N, 3), which the README repeats in every usage example with the comment that you load your point cloud as a NumPy array with shape (N, 3). That is a small but consequential design choice. A library that accepts only a dense float array of xyz triples can sit on top of any sensor pipeline, because converting a depth image or a LiDAR scan into an (N, 3) array is straightforward, and it can also sit inside an existing Open3D workflow without that framework being a requirement of the library itself.

Open3D appears only as an optional extra for visualisation. The README describes the combination as lightweight NumPy-based shape fitting with optional Open3D visualization, and the dependency groups put open3d in the dev group alongside invoke, flake8, isort, pylint, black and the documentation tooling, not in the runtime dependencies. The examples directory shows the split in practice, with a simple, a visual and an animation script per shape, where the visual and animation variants are the ones that need Open3D.

Fitting a plane, and reading the result as an equation

The plane example is the shortest path to understanding the API. You create the fitter, give it the points and a distance threshold, and it returns the best equation together with the inlier indices.

python
import pyransac3d as pyrsc

points = load_points(.) # Load your point cloud as a NumPy array with shape (N, 3)

plane1 = pyrsc.Plane()
best_eq, best_inliers = plane1.fit(points, 0.01)

The second argument is the threshold, and the README passes 0.01 for a plane fit. The return value is the plane equation Ax + By + Cz + D = 0, and the example output is [0.720, -0.253, 0.646, 1.100]. The threshold is the single most important parameter in the whole library, because it decides which points count as lying on the shape. Set it too small and a real surface yields few inliers; set it too large and unrelated geometry gets absorbed into the fit. The README does not document the units or the exact distance metric used, so the practical approach is to try a value close to your sensor's noise level and observe the inlier count.

The sphere fit returns a centre, a radius and its inliers

The sphere example shows the same pattern with a different return shape, since a sphere is described by a centre and a radius rather than by coefficients.

python
import pyransac3d as pyrsc

points = load_points(.) # Load your point cloud as a NumPy array with shape (N, 3)

sph = pyrsc.Sphere()
center, radius, inliers = sph.fit(points, thresh=0.4)

The README's example fits a noisy sphere with r = 5 centred at the origin, and the printed results are a centre of [0.010462385575072288, -0.2855090643954039, 0.02867848979091283] and a radius of 5.085218633039647. Note the threshold here is 0.4, an order of magnitude larger than the plane example, and that the fit is expressed with the keyword argument thresh rather than positionally. The returned radius of 5.085 against a true 5 shows the effect of noise on the estimate, which is the expected behaviour of a least-squares style fit on noisy inliers and a reminder to read the fitted parameters with the noise in mind. The point of the inlier list is that it tells you which measurements contributed, so you can segment the point cloud by shape and carry on with the rest.

The callback interface and the early stop example

RANSAC is iterative, and an iterative algorithm inside a robotics loop is a scheduling problem, not just a numerical one. The repository's examples directory includes early_stop_callback.py, and the documentation points to the animation examples where you can watch each RANSAC fitter update through its callback. That callback is the extension point: the fitter reports progress, and a caller can stop it. For a SLAM or mapping pipeline running at a fixed frame rate, that means the shape fit can be given a time budget and give up rather than hold the frame. The examples folder is organised per shape with simple, visual and animation variants, and the README notes that runnable examples of every shape are there, which is also the fastest way to see what a fitted parameter set actually looks like before wiring it into your own code. The repository also carries an early_stop_callback.py at the examples level rather than per shape, suggesting the callback is a shared concept across the fitters rather than a per-shape quirk.

Where a RANSAC fitter is the wrong tool

Three cases point elsewhere. The first is a problem where the shape is known in advance and only its parameters are unknown, for instance a calibrated camera and a planar target, where a least-squares fit is both faster and more accurate than a random-sampling search. RANSAC earns its cost by not knowing which points belong together, and if you already know, you are paying for robustness you do not need. The second is a pipeline that needs a full reconstruction, a mesh, a map or a trajectory, since this library returns shape parameters and inlier sets and stops there. The topics the project lists do include 3D reconstruction, but the mechanism is hypothesis generation, not reconstruction. The third is a very large cloud processed at interactive rates. RANSAC samples and tests repeatedly, so the cost scales with the number of hypotheses rather than the number of points alone, and a cloud of millions of points will need downsampling or a spatial index that you provide.

A separate practical limit is that RANSAC is a single-shape search. The README describes fitting one primitive to a cloud. Segmenting a scene into several surfaces and then fitting each is the caller's job, which for a real LiDAR scene means you need your own clustering or region growing step.

Version history, packaging and the documentation stack

The release history shows one long gap and then a burst. Version 0.6.0 was published on 2022-10-16 and v0.7.0 on 2026-08-18, with the last push to the repository on 2026-08-28. So the package sat at the same version for close to four years and then moved again, which tells you the recent release carries a substantial amount of accumulated work rather than an incremental tweak. The current version is 0.7.0 and the citation block in the README points at that version with a Zenodo DOI of 10.5281/zenodo.7212567, with a software citation rather than a paper. The repository is organised around modern Python tooling: a uv.lock for dependency locking, a tasks.py for the task runner, a pyproject.toml with pytest configuration pointing at the tests directory, and a pydoc-markdown.yml with mkdocs in the dev group for the documentation build. The documentation site is published from the doc/ directory, and the repository also holds a GETTING_STARTED.md, a ROADMAP.md, a CITATION.cff and a CONTRIBUTING.md. The maintainer is Leonardo Mariga.

Editorial conclusion

pyRANSAC-3D fits a robotics or computer vision team working with LiDAR or depth-camera point clouds that needs shape hypotheses, inliers and a threshold they control, in plain Python with a single dependency. It does not fit a team that wants a full reconstruction pipeline, since it returns shape parameters rather than a mesh or a map, and it does not fit a project that already has a C++ Open3D pipeline where the extra Python hop is unwelcome. Before you adopt it, check the threshold semantics against your sensor noise, since the distance you pass to fit is what decides inlier membership, and read the early_stop_callback example, because the callback interface is how you keep a RANSAC loop from running longer than your frame budget allows.

Frequently asked questions

What is pyRANSAC-3D?

It is an open source Python implementation of the Random Sample Consensus method that fits primitive shapes such as planes, cuboids and cylinders to point clouds, for applications including 3D SLAM, 3D reconstruction and object tracking. The supported shapes are Plane, Cylinder, Cone, Cuboid, Sphere, Line, Circle and Point.

How do I install pyRANSAC-3D and what does it require?

Install it from PyPI with pip install pyransac3d. The only runtime requirement is NumPy, and the project metadata sets requires-python to >=3.10. Open3D is optional and used for visualisation, and the README describes combining lightweight NumPy-based shape fitting with optional Open3D visualization.

How do I fit a plane to a point cloud with pyRANSAC-3D?

Create a Plane, then call fit with your (N, 3) NumPy array and a distance threshold, for example best_eq, best_inliers = plane1.fit(points, 0.01). The result is the plane equation Ax + By + Cz + D = 0 together with the indices of the inlier points.

What does the sphere fitter return in pyRANSAC-3D?

A centre, a radius and the inliers, so center, radius, inliers = sph.fit(points, thresh=0.4). In the README's example of a noisy sphere with r = 5 at the origin, the fitted radius comes out at 5.085218633039647, so the estimate carries the noise of the input.

How recent is pyRANSAC-3D?

Version 0.7.0 was published on 2026-08-18, after 0.6.0 which dates from 2022-10-16, and the last push to the repository was on 2026-08-28. The repository is not archived, the default branch is master, and the licence is Apache 2.0.

Official sources

  1. leomariga/pyRANSAC-3D on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/leomariga-pyransac-3d.svg)](https://hysenlabs.com/projects/leomariga-pyransac-3d)

Was this useful?