Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cylinder Fitting #13

Open
zhxd050946 opened this issue Nov 10, 2020 · 6 comments
Open

Cylinder Fitting #13

zhxd050946 opened this issue Nov 10, 2020 · 6 comments
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@zhxd050946
Copy link

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.
@leomariga leomariga added enhancement New feature or request good first issue Good for newcomers labels Dec 16, 2020
@Steven-Verkest-AI
Copy link

Steven-Verkest-AI commented Jul 22, 2021

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)

@leomariga
Copy link
Owner

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

@Destinycjk
Copy link

Destinycjk commented Jun 22, 2022

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

@Dejauxvue
Copy link

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.

@Liquidmasl
Copy link

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?

@Dejauxvue
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

6 participants