leomariga / pyransac-3d Goto Github PK
View Code? Open in Web Editor NEWA python tool for fitting primitives 3D shapes in point clouds using RANSAC algorithm
Home Page: https://leomariga.github.io/pyRANSAC-3D/
License: Apache License 2.0
A python tool for fitting primitives 3D shapes in point clouds using RANSAC algorithm
Home Page: https://leomariga.github.io/pyRANSAC-3D/
License: Apache License 2.0
Add RANSAC circle
Hi, is there any way to load a point cloud file, and find the different shapes hiding in it without prior knowledge? If I don't know what the shape is ahead of time, is there any way to use the algorithm?
Thanks a lot for you help!
The fitting error occurs when the plane of the space circle does not pass through the origin. For example, "points[:,2]=points[:,2]+5" in "test_circle.py". Shift all points up by 5, and the fit is incorrect
I was playing around with this library, and I found that because of the heavy usage of numpy (which releases the global interpeter lock), that a simple ThreadPoolExecutor
running the internals of the for
loops will allow for a 5x speedup on my laptop.
I was wondering if there was any interest in adding this to the library?
This is the API I was thinking would work. Each Ransac class would subclass this, to enable parallelization. Also, I added the ability to pass a seed, so that you can run deterministic ransac tests.
class BaseParallelRansac(ABC):
def __init__(self, seed=None, n_workers=None):
self.executor = ThreadPoolExecutor(max_workers=None)
self.random = Random(seed)
def fit(
self, points: np.ndarray, thresh: float = 0.05, max_iteration: int = 5000
) -> Tuple[List[int], List[int]]:
"""
:param points: A numpy array of points, of shape (# points, 3)
:param thresh: The distance threshold to include points as inliers
:param max_iteration: How many (parallel) Ransac iterations to run
:returns:
best_eq: A list of integers representing the best 'equation' for the primitive shape.
best_inliers: A list of indices of points that fit the shape.
"""
best_eq = []
best_inliers = []
jobs = ((self.random, points, float(thresh)) for _ in range(max_iteration))
for eq, point_id_inliers in self.executor.map(self.iteration, *zip(*jobs)):
if len(point_id_inliers) > len(best_inliers):
best_eq = eq
best_inliers = point_id_inliers
return best_eq, best_inliers
@staticmethod
@abstractmethod
def iteration(
self, random: Random, points: np.ndarray, thresh: float
) -> Tuple[List[int], List[int]]:
pass
class Cuboid(BaseParallelRansac):
def iteration(random, points, thresh):
# Implementation of a the inside of the for loop
...
Currently Ransac Plane fails when total of the provided points is 3 or 4.
Reproducible code
import pyransac3d as pyrsc
import numpy as np
plane = pyrsc.Plane()
pts = [[0,0,0],[0,1,0],[1,0,0]]
plane.fit(np.array(pts), 0.01)
And it receives error:
File "<stdin>", line 1, in <module>
File "/home/ardiya/.local/lib/python3.8/site-packages/pyransac3d/plane.py", line 46, in fit
id_samples = random.sample(range(1, n_points-1), 3)
File "/usr/lib/python3.8/random.py", line 363, in sample
raise ValueError("Sample larger than population or is negative")
ValueError: Sample larger than population or is negative
Env note:
pyransac3d 0.5.1 from pip install
I've just had some nasty issues installing on windows(10) due to 'aux' being a reserved word wrt to filenames (aux.py) ,
This issue prevents installation with pip, and leaves the user unable to open, rename, or delete the file - making it effectively impossible to clean up afterwards.
I have thousands of shapes, and I don't want the fitting function to print the number of points for each shape. Could you disable that option?
Thanks in advance!
Hi there,
I just started using this library, and I am also new to computational geometry so please bear with me..
I am trying to fit a cuboid to some points, but I just realized that the Cuboid.fit()
result is just returning 3 planes. I expected it to return 6 planes, as I don't see how 3 planes can fully parametrize a cuboid object.
I felt pretty dumb and was sure I was missing something, so I asked ChatGPT which seems to agree that we need 6 planes and not 3.. now I am even more confused.
What am I missing?
The cylinder fitting with RANSAC method is very unstable. There are some ways to improve the performance of RANSAC:
pyRANSAC-3D/pyransac3d/cuboid.py
Line 73 in 28b0735
Add sphere RANSAC detection.
Hey,
I would like to attach a plane equation to a point cloud in order to be able to compare new point clouds with the plane later.
At first it looked fine, but over time I noticed that my plane equation is always aligned parallel to the Z-plane. As can be seen here:
My plan equation parameter = [0,0,1,-832]
This is my code:
planeObj = pyrsc.Plane() best_eq, best_inliers = planeObj.fit(pointCloudPoints, thresh=0.001, minPoints=1000, maxIteration=10000)
I'm using round about 200k points for the fitting.
Now I am not sure if I have set my parameters correctly and hope that you can help me here.
For comparison, here is a picture with a different RANSAC algorithm:
Here are the plane equationparameter = [-2.62341300e-05 4.57572034e-05 -1.20127911e-03 9.99999277e-01]
This code I code from here https://github.com/falcondai/py-ransac
I hope you have a tip for me.
Thank you.
Update all classes to have a minimum number of points to be considered an inliers
Add Torus implementation
When we detect circles from point sets, the resulting circle is at a wrong place. Here an example (green - inliers):
After checking the code, I guess the bug comes from the line 93 in file "circle.py".
I changed it to "p_center = [p_center_x, p_center_y, P_rot[0, 2]]" then the result becomes:
Could you check the code? I'm open for further discussion.
Right now we cannot call test_{primitive}.py
from the test folder because the import is not on the right folder level.
Develop 3D point implementation of RANSAC.
Thank you very much for this repo! I learned a lot form it and enjoyed working with it.
Do you know if it is possible to restrict the solution of the cuboid by imposing a known volume (or width, height, lenght) or the cuboid? I use the cuboid.fit
algorithm on a pointcloud containing multiple objects. Unfortunately, the algorithm returned a cuboid that returned a solution comprising all distinct object. I tried to restrict the algorithm as followes:
lenght = pts[pt_id_inliers, 0].max() - pts[pt_id_inliers, 0].min()
height = pts[pt_id_inliers, 1].max() - pts[pt_id_inliers, 1].min()
width = pts[pt_id_inliers, 2].max() - pts[pt_id_inliers, 2].min()
volume = height * length * width
if volume > max_volume:
continue
Where max_volume
is a function argument to the fit
function. Strangely, the proposed solution of the algorithm does not change from one iteration to the loop to the other and at the end the algorithm does not find any solution.
Do yo have any idea how one could impose a restricted size of the cuboid?
Add cone RANSAC implementation
Add line fit with RANSAC. Select two points and verify distance from nearby points
Hey there,
this is more of a request then an issue. Your work is nice and lightweighted. Simple to use and works very efficient. This is what I can say after 20 min of use.
What I miss or better what I would like to have is a method to compare my pointCloud with the calculated plane. The result of this comparison should be pointCloud where each pixel represents the distance to calculated plane equation.
What do you think about this?
Encountered the error when plane fitting:
/usr/local/lib/python3.8/dist-packages/pyransac3d/plane.py:59: RuntimeWarning: invalid value encountered in true_divide
vecC = vecC / np.linalg.norm(vecC)
Code Attached:
def plane_fit(pointList):
[X, Y, Z, I] = pointList
p_arr = np.empty((len(X), 3), float)
P_color_arr = np.empty((0, 3), int)
print('print len of full points')
print(len(X))
for i in range(len(X)):
p_arr = np.append(p_arr, np.array([[X[i], Y[i], Z[i]]]), axis=0)
P_color_arr = np.append(p_arr, np.array([[I[i], 0, 0]]), axis=0)
plane1 = pyrsc.Plane()
# Load saved point cloud and visualize it
pcd_load = o3d.geometry.PointCloud()
pcd_load.points = o3d.utility.Vector3dVector(p_arr)
pcd_load.colors = o3d.utility.Vector3dVector(P_color_arr)
print("pcd created")
# o3d.visualization.draw_geometries([pcd_load])
points = np.asarray(pcd_load.points)
best_eq, best_inliers = plane1.fit(points, 1)
X_new = []
Y_new = []
Z_new = []
I_new = []
print("Printing len of inliners")
print(len(best_inliers))
print("Equation:")
print(best_eq)
for i in range(len(p_arr)):
if i in best_inliers:
X_new.append(p_arr[i][0])
Y_new.append(p_arr[i][1])
Z_new.append(p_arr[i][2])
I_new.append(1)
print(len(X_new))
return [X_new, Y_new, Z_new, I_new]
I ran the 'tests/test_plane.py ' but got the following error:
>>> python tests/test_plane.py
RPly: Unable to open file
[Open3D WARNING] Read PLY failed: unable to open file: dataset/caixa.ply
0
Traceback (most recent call last):
File "tests/test_plane.py", line 15, in <module>
best_eq, best_inliers = plano1.fit(points, 0.01)
File "/Users/opt/anaconda3/envs/open3d/lib/python3.8/site-packages/pyransac3d/plane.py", line 46, in fit
id_samples = random.sample(range(1, n_points-1), 3)
File "/Users/opt/anaconda3/envs/open3d/lib/python3.8/random.py", line 363, in sample
raise ValueError("Sample larger than population or is negative")
ValueError: Sample larger than population or is negative
When processing larger pointclouds, the processing time can take a while, especially with a higher max_iteration
value. It would be helpful to have an argument for a progress callback function. I have seen a similar design pattern with a photogrammetry software Metashape (see documentation here https://www.agisoft.com/pdf/metashape_python_api_1_8_0.pdf)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.