Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm using skimage.measure.marching_cubes to extract a surface, defined as faces and vertices . marching_cubes also outputs values for each face.

How do I "smooth" these values (the actual smoothing could be a low-pass filter, median filter etc)? I thought that one way to achieve this would be to project, or to represent this surface in 2D, and then apply standard filters, but I can't think of how to do this from a list of faces and vertices.

The reason for this "smoothing" is because the values are not informative at the scale of a single face of the surface, but over larger areas of the surface represented by many faces.

Thanks in advance!

I eventually found a way to do this, based on MATLAB code from this paper:

Welf et al. "Quantitative Multiscale Cell Imaging in Controlled 3D Microenvironments" in Developmental Cell, 2016, Vol 36, Issue 4, p462-475

def median_filter_surface(faces, verts, measure, radius, p_norm=2):
    from scipy import spatial
    import numpy as np
    # INPUT:
    # faces: triangular surface faces - defined by 3 vertices
    # verts: the above vertices, defined by x,y,z coordinates
    # measure: the value related to each face that needs to be filtered
    # radius: the radius for median filtering (larger = more filtering)
    # p_norm: distance metric for the radius, default 2 (euclidian)
    # OUTPUT:
    # measure_med_filt: the "measure" after filtering
    num_faces = len(faces)
    face_centres = np.zeros((num_faces, 3))
    # get face centre positions in 3D space (from vert coordinates)
    for face in range(0, num_faces):
        face_centres[face, :] = np.mean(verts[faces[face, :], :], 0)
    # return all other points within a radius
    tree = spatial.KDTree(face_centres)
    faces_in_radius = tree.query_ball_point(face_centres, radius, p_norm)
    measure_med_filt = np.zeros(len(faces))
    for face in range(0, len(faces)):
        measure_med_filt[face] = np.median(measure[faces_in_radius[face]])
    return measure_med_filt
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.