pyRANSAC-3D icon indicating copy to clipboard operation
pyRANSAC-3D copied to clipboard

Cylinder Fitting

Open zhxd050946 opened this issue 3 years ago • 6 comments

The cylinder fitting with RANSAC method is very unstable. There are some ways to improve the performance of RANSAC:

  1. add or compute the normal components to the point cloud data.
  2. 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.
  3. use MSAC or MLESAC instead of RANSAC.

zhxd050946 avatar Nov 10 '20 06:11 zhxd050946

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

side-view top_view

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 avatar Jul 22 '21 10:07 Steven-Verkest-AI

@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.

leomariga avatar Jul 24 '21 17:07 leomariga

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. image

Destinycjk avatar Jun 22 '22 07:06 Destinycjk

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.

Dejauxvue avatar May 24 '23 13:05 Dejauxvue

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?

Liquidmasl avatar Jul 21 '23 10:07 Liquidmasl

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.

Dejauxvue avatar Jul 24 '23 09:07 Dejauxvue