pyRANSAC-3D
pyRANSAC-3D copied to clipboard
Cylinder Fitting
The cylinder fitting with RANSAC method is very unstable. There are some ways to improve the performance of RANSAC:
- add or compute the normal components to the point cloud data.
- take the RANSAC result as an initial guess, optimize the cylinder coefficents with the inlier points and normals using nonlinear optimization algorithms, such as LM algorithm.
- use MSAC or MLESAC instead of RANSAC.
I used the cylinder fitting algo from pyransac-3d but got weird results.
I'm trying to find the cylindric shape in a pointcloud
LEGEND: grey points = all points orange points = inliers used by pyransac to fit the cylinder with (values returned by pyransac) black dot = center value of the cylinder returned by pyransac (value return by pyransac) red = the cylinder found by pyransac
I find it weird that in this pointcloud the cylindric shape is pretty clear, and the inlier points seems legit, but the results seems to be a cylinder with a radius that's 3cm to small , and it seems translated.
Is this some common mistake in pyransac, or did I do something wrong ? Or do you see some flaw in the way I setted up my code?
cylinder = pyrsc.Cylinder()
center, axis, radius, inliers = cylinder.fit(np.array(points), thresh=0.1, maxIteration=100)
# points, contains XYZ values of the poincloud points
fig = plt.figure(figsize=(10, 10))
fig.canvas.set_window_title('')
fig.suptitle('RANSAC CYLINDER FITTING ON SEGMENT')
ax = plt.axes(projection="3d")
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.xlim([-1, 1])
plt.ylim([-1, 1])
ax.set_zlim(-1, -2)
# PLOT ALL POINTS
ax.scatter(X, Y, Z, s=1, alpha = 0.01, c='grey', label='all_points')
# PLOT CENTER OF CYLINDER (pyransac)
ax.scatter(center[0], center[1], center[2], s=20, c='black', label='center of cylinder segment')
# PLOT INLIERS CYLINDER (pyransac)
ax.scatter(inliers_X, inliers_Y, inliers_Z, s=1, alpha= 0.25, c='orange', label='inliers')
# PLOT CYLINDER SEGMENT
def data_for_cylinder_along_z(center_x, center_y, center_z, radius, height_z):
z = np.linspace(center_z, center_z + height_z, 50)
theta = np.linspace(0, 2 * np.pi, 50)
theta_grid, z_grid = np.meshgrid(theta, z)
x_grid = radius * np.cos(theta_grid) + center_x
y_grid = radius * np.sin(theta_grid) + center_y
return x_grid, y_grid, z_grid
Xc, Yc, Zc = data_for_cylinder_along_z(center[0], center[1], center[2], radius, 0.62) # TODO calculate heigth
ax.plot_surface(Xc, Yc, Zc, color='red', alpha=0.75)
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), shadow=True, ncol=2)
plt.show()
plt.close(fig)
@Steven-Verkest-AI Out cylinder fit method is not good. I believe your code is correctly implemented
You can try to increase the number of maxIteration
. However, we are currently searching for a better method.
Thank you very much for sharing! There seems to be an error which results in the problem in line 91 in Cylinder.py. It should be changed as " p_center = [p_center_x, p_center_y, P_rot[0,2]] " and the result will be better. If you want to further imporve the fitting accuracy, you can add some other geometric constraints.
Correct me, if I am wrong, but shouldn't RANSAC for a cylinder sample at least 4 points? It looks like the current implementation assumes the 3 sampled points are in a plane orthogonal to the cylinder axis. I'll try to make an implementation with 4 sampled points. Maybe, you can provide some data sets so that I can verify if my implementation is more stable than the current.
Correct me, if I am wrong, but shouldn't RANSAC for a cylinder sample at least 4 points? It looks like the current implementation assumes the 3 sampled points are in a plane orthogonal to the cylinder axis. I'll try to make an implementation with 4 sampled points. Maybe, you can provide some data sets so that I can verify if my implementation is more stable than the current.
Any chance you found something out?
A cylinder has 5 degrees of freedom, so at least 5 points are necessary to be left with a finite set of possible cylinders fitting your samples. However, solving the actual equation seems to be quite hard (https://math.stackexchange.com/questions/2878112/recovering-a-cylinder-from-five-points). Other frameworks for cylinder fitting use point normals as well and achieve good results.