Exemplo n.º 1
0
def zernike_moments(points,
                    faces,
                    order=10,
                    scale_input=True,
                    decimate_fraction=0,
                    decimate_smooth=0,
                    verbose=False):
    """
    Compute the Zernike moments of a surface patch of points and faces.

    Optionally decimate the input mesh.

    Note::
      Decimation sometimes leads to an error of "Segmentation fault: 11"
      (Twins-2-1 left label 14 gives such an error only when decimated.)

    Parameters
    ----------
    points : list of lists of 3 floats
        x,y,z coordinates for each vertex
    faces : list of lists of 3 integers
        each list contains indices to vertices that form a triangle on a mesh
    order : integer
        order of the moments being calculated
    scale_input : bool
        translate and scale each object so it is bounded by a unit sphere?
        (this is the expected input to zernike_moments())
    decimate_fraction : float
        fraction of mesh faces to remove for decimation (0 for no decimation)
    decimate_smooth : integer
        number of smoothing steps for decimation
    verbose : bool
        print statements?

    Returns
    -------
    descriptors : list of floats
        Zernike descriptors

    Examples
    --------
    >>> # Example 1: simple cube (decimation results in a Segmentation Fault):
    >>> import numpy as np
    >>> from mindboggle.shapes.zernike.zernike import zernike_moments
    >>> points = [[0,0,0], [1,0,0], [0,0,1], [0,1,1],
    ...           [1,0,1], [0,1,0], [1,1,1], [1,1,0]]
    >>> faces = [[0,2,4], [0,1,4], [2,3,4], [3,4,5], [3,5,6], [0,1,7]]
    >>> order = 3
    >>> scale_input = True
    >>> decimate_fraction = 0
    >>> decimate_smooth = 0
    >>> verbose = False
    >>> descriptors = zernike_moments(points, faces, order, scale_input,
    ...     decimate_fraction, decimate_smooth, verbose)
    >>> print(np.array_str(np.array(descriptors),
    ...       precision=5, suppress_small=True))
    [ 0.09189  0.09357  0.04309  0.06466  0.0382   0.04138]

    Example 2: Twins-2-1 left postcentral pial surface -- NO decimation:
               (zernike_moments took 142 seconds for order = 3 with no decimation)

    >>> from mindboggle.shapes.zernike.zernike import zernike_moments
    >>> from mindboggle.mio.vtks import read_vtk
    >>> from mindboggle.guts.mesh import keep_faces
    >>> from mindboggle.mio.fetch_data import prep_tests
    >>> urls, fetch_data = prep_tests()
    >>> label_file = fetch_data(urls['left_freesurfer_labels'], '', '.vtk')
    >>> points, f1,f2, faces, labels, f3,f4,f5 = read_vtk(label_file)
    >>> I22 = [i for i,x in enumerate(labels) if x==1022] # postcentral
    >>> faces = keep_faces(faces, I22)
    >>> order = 3
    >>> scale_input = True
    >>> decimate_fraction = 0
    >>> decimate_smooth = 0
    >>> verbose = False
    >>> descriptors = zernike_moments(points, faces, order, scale_input,
    ...     decimate_fraction, decimate_smooth, verbose)
    >>> print(np.array_str(np.array(descriptors),
    ...       precision=5, suppress_small=True))
    [ 0.00471  0.0084   0.00295  0.00762  0.0014   0.00076]

    Example 3: left postcentral + pars triangularis pial surfaces:

    >>> from mindboggle.mio.vtks import read_vtk, write_vtk
    >>> points, f1,f2, faces, labels, f3,f4,f5 = read_vtk(label_file)
    >>> I20 = [i for i,x in enumerate(labels) if x==1020] # pars triangularis
    >>> I22 = [i for i,x in enumerate(labels) if x==1022] # postcentral
    >>> I22.extend(I20)
    >>> faces = keep_faces(faces, I22)
    >>> order = 3
    >>> scale_input = True
    >>> decimate_fraction = 0
    >>> decimate_smooth = 0
    >>> verbose = False
    >>> descriptors = zernike_moments(points, faces, order, scale_input,
    ...     decimate_fraction, decimate_smooth, verbose)
    >>> print(np.array_str(np.array(descriptors),
    ...       precision=5, suppress_small=True))
    [ 0.00586  0.00973  0.00322  0.00818  0.0013   0.00131]

    View both segments (skip test):

    >>> from mindboggle.mio.plots import plot_surfaces # doctest: +SKIP
    >>> from mindboggle.mio.vtks import rewrite_scalars # doctest: +SKIP
    >>> scalars = -1 * np.ones(np.shape(labels)) # doctest: +SKIP
    >>> scalars[I22] = 1 # doctest: +SKIP
    >>> rewrite_scalars(label_file, 'test_two_labels.vtk', scalars,
    ...                 'two_labels', scalars) # doctest: +SKIP
    >>> plot_surfaces(vtk_file) # doctest: +SKIP

    """
    import numpy as np

    from mindboggle.guts.mesh import reindex_faces_0to1
    from mindboggle.guts.mesh import decimate
    from mindboggle.shapes.zernike.pipelines import DefaultPipeline as Pipeline

    # Convert 0-indices (Python) to 1-indices (Matlab) for all face indices:
    index1 = False  # already done elsewhere in the code
    if index1:
        faces = reindex_faces_0to1(faces)

    # Convert lists to numpy arrays:
    if isinstance(points, list):
        points = np.array(points)
    if isinstance(faces, list):
        faces = np.array(faces)

    # ------------------------------------------------------------------------
    # Translate all points so that they are centered at their mean,
    # and scale them so that they are bounded by a unit sphere:
    # ------------------------------------------------------------------------
    if scale_input:
        center = np.mean(points, axis=0)
        points = points - center
        maxd = np.max(np.sqrt(np.sum(points**2, axis=1)))
        points /= maxd

    # ------------------------------------------------------------------------
    # Decimate surface:
    # ------------------------------------------------------------------------
    if 0 < decimate_fraction < 1:
        points, faces, u1, u2 = decimate(points,
                                         faces,
                                         decimate_fraction,
                                         decimate_smooth, [],
                                         save_vtk=False)

        # Convert lists to numpy arrays:
        points = np.array(points)
        faces = np.array(faces)

    # ------------------------------------------------------------------------
    # Multiprocessor pipeline:
    # ------------------------------------------------------------------------
    pl = Pipeline()

    # ------------------------------------------------------------------------
    # Geometric moments:
    # ------------------------------------------------------------------------
    G = pl.geometric_moments_exact(points, faces, order)

    # ------------------------------------------------------------------------
    # ------------------------------------------------------------------------
    Z = pl.zernike(G, order)

    # ------------------------------------------------------------------------
    # Extract Zernike descriptors:
    # ------------------------------------------------------------------------
    descriptors = pl.feature_extraction(Z, order).tolist()

    if verbose:
        print("Zernike moments: {0}".format(descriptors))

    return descriptors
Exemplo n.º 2
0
def zernike_moments(points, faces, order=10, scale_input=True,
                    decimate_fraction=0, decimate_smooth=0, verbose=False):
    """
    Compute the Zernike moments of a surface patch of points and faces.

    Optionally decimate the input mesh.

    Note::
      Decimation sometimes leads to an error of "Segmentation fault: 11"
      (Twins-2-1 left label 14 gives such an error only when decimated.)

    Parameters
    ----------
    points : list of lists of 3 floats
        x,y,z coordinates for each vertex
    faces : list of lists of 3 integers
        each list contains indices to vertices that form a triangle on a mesh
    order : integer
        order of the moments being calculated
    scale_input : bool
        translate and scale each object so it is bounded by a unit sphere?
        (this is the expected input to zernike_moments())
    decimate_fraction : float
        fraction of mesh faces to remove for decimation (0 for no decimation)
    decimate_smooth : integer
        number of smoothing steps for decimation
    verbose : bool
        print statements?

    Returns
    -------
    descriptors : list of floats
        Zernike descriptors

    Examples
    --------
    >>> # Example 1: simple cube (decimation results in a Segmentation Fault):
    >>> import numpy as np
    >>> from mindboggle.shapes.zernike.zernike import zernike_moments
    >>> points = [[0,0,0], [1,0,0], [0,0,1], [0,1,1],
    ...           [1,0,1], [0,1,0], [1,1,1], [1,1,0]]
    >>> faces = [[0,2,4], [0,1,4], [2,3,4], [3,4,5], [3,5,6], [0,1,7]]
    >>> order = 3
    >>> scale_input = True
    >>> verbose = False
    >>> descriptors = zernike_moments(points, faces, order, scale_input,
    ...     verbose)
    >>> print(np.array_str(np.array(descriptors),
    ...       precision=5, suppress_small=True))
    [ 0.09189  0.09357  0.04309  0.06466  0.0382   0.04138]

    Example 2: Twins-2-1 left postcentral pial surface -- NO decimation:
               (zernike_moments took 142 seconds for order = 3 with no decimation)

    >>> from mindboggle.mio.vtks import read_vtk
    >>> from mindboggle.guts.mesh import keep_faces
    >>> from mindboggle.mio.fetch_data import prep_tests
    >>> urls, fetch_data = prep_tests()
    >>> label_file = fetch_data(urls['left_freesurfer_labels'])
    >>> points, f1,f2, faces, labels, f3,f4,f5 = read_vtk(label_file)
    >>> I22 = [i for i,x in enumerate(labels) if x==1022] # postcentral
    >>> faces = keep_faces(faces, I22)
    >>> order = 3
    >>> scale_input = True
    >>> verbose = False
    >>> descriptors = zernike_moments(points, faces, order, scale_input,
    ...     verbose)
    >>> print(np.array_str(np.array(descriptors),
    ...       precision=5, suppress_small=True))
    [ 0.00471  0.0084   0.00295  0.00762  0.0014   0.00076]

    Example 3: left postcentral + pars triangularis pial surfaces:

    >>> from mindboggle.mio.vtks import read_vtk, write_vtk
    >>> points, f1,f2, faces, labels, f3,f4,f5 = read_vtk(label_file)
    >>> I20 = [i for i,x in enumerate(labels) if x==1020] # pars triangularis
    >>> I22 = [i for i,x in enumerate(labels) if x==1022] # postcentral
    >>> I22.extend(I20)
    >>> faces = keep_faces(faces, I22)
    >>> order = 3
    >>> scale_input = True
    >>> verbose = False
    >>> descriptors = zernike_moments(points, faces, order, scale_input,
    ...     verbose)
    >>> print(np.array_str(np.array(descriptors),
    ...       precision=5, suppress_small=True))
    [ 0.00586  0.00973  0.00322  0.00818  0.0013   0.00131]

    View both segments (skip test):

    >>> from mindboggle.mio.plots import plot_surfaces
    >>> scalars = -1 * np.ones(np.shape(labels))
    >>> scalars[I22] = 1
    >>> vtk_file = 'test_two_labels.vtk'
    >>> # Note: mismatch in the following command:
    >>> write_vtk(vtk_file, points, [],[], faces, scalars, 'scalars', 'int')
    >>> plot_surfaces(vtk_file) # doctest: +SKIP

    """
    import numpy as np

    from mindboggle.guts.mesh import reindex_faces_0to1
    from mindboggle.guts.mesh import decimate
    from .pipelines import DefaultPipeline as ZernikePipeline

    # Convert 0-indices (Python) to 1-indices (Matlab) for all face indices:
    index1 = False  # already done elsewhere in the code
    if index1:
        faces = reindex_faces_0to1(faces)

    # Convert lists to numpy arrays:
    if isinstance(points, list):
        points = np.array(points)
    if isinstance(faces, list):
        faces = np.array(faces)

    #-------------------------------------------------------------------------
    # Translate all points so that they are centered at their mean,
    # and scale them so that they are bounded by a unit sphere:
    #-------------------------------------------------------------------------
    if scale_input:
        center = np.mean(points, axis=0)
        points = points - center
        maxd = np.max(np.sqrt(np.sum(points**2, axis=1)))
        points = points / maxd

    #-------------------------------------------------------------------------
    # Decimate surface:
    #-------------------------------------------------------------------------
    if 0 < decimate_fraction < 1:
        points, faces, u1,u2 = decimate(points, faces,
            decimate_fraction, decimate_smooth, [], save_vtk=False)

        # Convert lists to numpy arrays:
        points = np.array(points)
        faces = np.array(faces)

    #-------------------------------------------------------------------------
    # Multiprocessor pipeline:
    #-------------------------------------------------------------------------
    pl = ZernikePipeline()

    #-------------------------------------------------------------------------
    # Geometric moments:
    #-------------------------------------------------------------------------
    G = pl.geometric_moments_exact(points, faces, order)

    #
    Z = pl.zernike(G, order)

    #-------------------------------------------------------------------------
    # Extract Zernike descriptors:
    #-------------------------------------------------------------------------
    descriptors = pl.feature_extraction(Z, order).tolist()

    if verbose:
        print("Zernike moments: {0}".format(descriptors))

    return descriptors
Exemplo n.º 3
0
def zernike_moments(points,
                    faces,
                    order=10,
                    scale_input=True,
                    decimate_fraction=0,
                    decimate_smooth=0,
                    pl_cls=None):
    """
    Compute the Zernike moments of a surface patch of points and faces.

    Optionally decimate the input mesh.

    Note::
      Decimation sometimes leads to an error of "Segmentation fault: 11"
      (Twins-2-1 left label 14 gives such an error only when decimated.)

    Parameters
    ----------
    points : list of lists of 3 floats
        x,y,z coordinates for each vertex
    faces : list of lists of 3 integers
        each list contains indices to vertices that form a triangle on a mesh
    order : integer
        order of the moments being calculated
    scale_input : Boolean
        translate and scale each object so it is bounded by a unit sphere?
        (this is the expected input to zernike_moments())
    decimate_fraction : float
        fraction of mesh faces to remove for decimation (0 for no decimation)
    decimate_smooth : integer
        number of smoothing steps for decimation

    Returns
    -------
    descriptors : list of floats
        Zernike descriptors

    Examples
    --------
    >>> # Example 1: simple cube (decimation results in a Segmentation Fault):
    >>> from mindboggle.shapes.zernike.zernike import zernike_moments
    >>> points = [[0,0,0], [1,0,0], [0,0,1], [0,1,1], [1,0,1], [0,1,0], [1,1,1], [1,1,0]]
    >>> faces = [[0,2,4], [0,1,4], [2,3,4], [3,4,5], [3,5,6], [0,1,7]]
    >>> order = 3
    >>> scale_input = True
    >>> zernike_moments(points, faces, order, scale_input)
    [0.0918881492369654,
     0.09357431096617608,
     0.04309029164656885,
     0.06466432586854755,
     0.03820155248327533,
     0.04138011726544602]
    >>> # Example 2: simple cube (with inner diagonal plane):
    >>> # (decimation doesn't have any effect)
    >>> import os
    >>> from mindboggle.mio.vtks import read_vtk
    >>> from mindboggle.shapes.zernike.zernike import zernike_moments
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> vtk_file = os.path.join(path, 'cube.vtk')
    >>> faces, u1,u2, points, u3,u4,u5,u6 = read_vtk(vtk_file)
    >>> order = 3
    >>> scale_input = True
    >>> zernike_moments(points, faces, order, scale_input)
    [0.0,
     1.5444366221695725e-21,
     0.0,
     2.081366518964347e-21,
     5.735003646768394e-05,
     2.433866250546253e-21]

    Arthur Mikhno's result:
    0
    0
    0.2831
    10.6997
    2.1352
    11.8542
    >>> # Example 2.5: Parallelepiped.vtk:
    >>> import os
    >>> from mindboggle.mio.vtks import read_vtk
    >>> from mindboggle.shapes.zernike.zernike import zernike_moments
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> vtk_file = os.path.join(path, 'Parallelepiped.vtk')
    >>> faces, u1,u2, points, u3,u4,u5,u6 = read_vtk(vtk_file)
    >>> order = 3
    >>> scale_input = True
    >>> zernike_moments(points, faces, order, scale_input)
    [0.2652000150907399,
     0.27006648207389017,
     6.902814314591948e-09,
     7.901431343883835e-09,
     0.12685697496878662,
     5.560135951999606e-09]
    Arthur Mikhno's result:
    0.0251
    0.0310
    0.0255
    0.0451
    0.0189
    0.0133
    >>> # Example 3: Twins-2-1 left postcentral pial surface -- NO decimation:
    >>> # (zernike_moments took 142 seconds for order = 3 with no decimation)
    >>> import os
    >>> from mindboggle.mio.vtks import read_vtk
    >>> from mindboggle.guts.mesh import remove_faces
    >>> from mindboggle.shapes.zernike.zernike import zernike_moments
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> label_file = os.path.join(path, 'arno', 'labels', 'lh.labels.DKT31.manual.vtk')
    >>> faces, u1,u2, points, u3, labels, u4,u5 = read_vtk(label_file)
    >>> I22 = [i for i,x in enumerate(labels) if x==22] # postcentral
    >>> faces = remove_faces(faces, I22)
    >>> order = 3
    >>> scale_input = True
    >>> zernike_moments(points, faces, order, scale_input)
     [0.005558794553842859,
     0.009838755429501177,
     0.003512500896236744,
     0.00899042745665395,
     0.001672289910738449,
     0.000919469614081582]
    >>> # Example 5: left postcentral + pars triangularis pial surfaces:
    >>> import os
    >>> from mindboggle.mio.vtks import read_vtk, write_vtk
    >>> from mindboggle.guts.mesh import remove_faces
    >>> from mindboggle.shapes.zernike.zernike import zernike_moments
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> label_file = os.path.join(path, 'arno', 'labels', 'lh.labels.DKT31.manual.vtk')
    >>> faces, u1,u2, points, u3, labels, u4,u5 = read_vtk(label_file)
    >>> I20 = [i for i,x in enumerate(labels) if x==20] # pars triangularis
    >>> I22 = [i for i,x in enumerate(labels) if x==22] # postcentral
    >>> I22.extend(I20)
    >>> faces = remove_faces(faces, I22)
    >>> order = 3
    >>> scale_input = True
    >>> zernike_moments(points, faces, order, scale_input)
    [0.006591540793309832,
     0.010749937070447451,
     0.0034900573103799214,
     0.008972460360983864,
     0.0018220183025464518,
     0.0016893113500293917]
    >>> # View both segments:
    >>> from mindboggle.mio.plots import plot_surfaces
    >>> scalars = -1*np.ones(np.shape(labels))
    >>> scalars[I22] = 1
    >>> vtk_file = 'test_two_labels.vtk'
    >>> write_vtk(vtk_file, points, [],[], faces, scalars, scalar_names='scalars', scalar_type='int')
    >>> plot_surfaces(vtk_file)

    """
    import numpy as np

    from mindboggle.guts.mesh import reindex_faces_0to1
    from mindboggle.guts.mesh import decimate
    if pl_cls is None:
        from .pipelines import DefaultPipeline as ZernikePipeline
    else:
        ZernikePipeline = pl_cls

    # Convert 0-indices (Python) to 1-indices (Matlab) for all face indices:
    index1 = False  # already done elsewhere in the code
    if index1:
        faces = reindex_faces_0to1(faces)

    # Convert lists to numpy arrays:
    if isinstance(points, list):
        points = np.array(points)
    if isinstance(faces, list):
        faces = np.array(faces)

    #-------------------------------------------------------------------------
    # Translate all points so that they are centered at their mean,
    # and scale them so that they are bounded by a unit sphere:
    #-------------------------------------------------------------------------
    if scale_input:
        center = np.mean(points, axis=0)
        points = points - center
        maxd = np.max(np.sqrt(np.sum(points**2, axis=1)))
        points = points / maxd

    #-------------------------------------------------------------------------
    # Decimate surface:
    #-------------------------------------------------------------------------
    if 0 < decimate_fraction < 1:
        points, faces, u1, u2 = decimate(points,
                                         faces,
                                         decimate_fraction,
                                         decimate_smooth, [],
                                         save_vtk=False)

        # Convert lists to numpy arrays:
        points = np.array(points)
        faces = np.array(faces)

    #-------------------------------------------------------------------------
    # Multiprocessor pipeline:
    #-------------------------------------------------------------------------
    pl = ZernikePipeline()

    #-------------------------------------------------------------------------
    # Geometric moments:
    #-------------------------------------------------------------------------
    G = pl.geometric_moments_exact(points, faces, order)

    #
    Z = pl.zernike(G, order)

    #-------------------------------------------------------------------------
    # Extract Zernike descriptors:
    #-------------------------------------------------------------------------
    descriptors = pl.feature_extraction(Z, order).tolist()

    return descriptors
Exemplo n.º 4
0
def zernike_moments(points, faces, order=10, scale_input=True,
                    decimate_fraction=0, decimate_smooth=0, pl_cls=None):
    """
    Compute the Zernike moments of a surface patch of points and faces.

    Optionally decimate the input mesh.

    Note::
      Decimation sometimes leads to an error of "Segmentation fault: 11"
      (Twins-2-1 left label 14 gives such an error only when decimated.)

    Parameters
    ----------
    points : list of lists of 3 floats
        x,y,z coordinates for each vertex
    faces : list of lists of 3 integers
        each list contains indices to vertices that form a triangle on a mesh
    order : integer
        order of the moments being calculated
    scale_input : Boolean
        translate and scale each object so it is bounded by a unit sphere?
        (this is the expected input to zernike_moments())
    decimate_fraction : float
        fraction of mesh faces to remove for decimation (0 for no decimation)
    decimate_smooth : integer
        number of smoothing steps for decimation

    Returns
    -------
    descriptors : list of floats
        Zernike descriptors

    Examples
    --------
    >>> # Example 1: simple cube (decimation results in a Segmentation Fault):
    >>> from mindboggle.shapes.zernike.zernike import zernike_moments
    >>> points = [[0,0,0], [1,0,0], [0,0,1], [0,1,1], [1,0,1], [0,1,0], [1,1,1], [1,1,0]]
    >>> faces = [[0,2,4], [0,1,4], [2,3,4], [3,4,5], [3,5,6], [0,1,7]]
    >>> order = 3
    >>> scale_input = True
    >>> zernike_moments(points, faces, order, scale_input)
    [0.0918881492369654,
     0.09357431096617608,
     0.04309029164656885,
     0.06466432586854755,
     0.03820155248327533,
     0.04138011726544602]
    >>> # Example 2: simple cube (with inner diagonal plane):
    >>> # (decimation doesn't have any effect)
    >>> import os
    >>> from mindboggle.mio.vtks import read_vtk
    >>> from mindboggle.shapes.zernike.zernike import zernike_moments
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> vtk_file = os.path.join(path, 'cube.vtk')
    >>> faces, u1,u2, points, u3,u4,u5,u6 = read_vtk(vtk_file)
    >>> order = 3
    >>> scale_input = True
    >>> zernike_moments(points, faces, order, scale_input)
    [0.0,
     1.5444366221695725e-21,
     0.0,
     2.081366518964347e-21,
     5.735003646768394e-05,
     2.433866250546253e-21]

    Arthur Mikhno's result:
    0
    0
    0.2831
    10.6997
    2.1352
    11.8542
    >>> # Example 2.5: Parallelepiped.vtk:
    >>> import os
    >>> from mindboggle.mio.vtks import read_vtk
    >>> from mindboggle.shapes.zernike.zernike import zernike_moments
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> vtk_file = os.path.join(path, 'Parallelepiped.vtk')
    >>> faces, u1,u2, points, u3,u4,u5,u6 = read_vtk(vtk_file)
    >>> order = 3
    >>> scale_input = True
    >>> zernike_moments(points, faces, order, scale_input)
    [0.2652000150907399,
     0.27006648207389017,
     6.902814314591948e-09,
     7.901431343883835e-09,
     0.12685697496878662,
     5.560135951999606e-09]
    Arthur Mikhno's result:
    0.0251
    0.0310
    0.0255
    0.0451
    0.0189
    0.0133
    >>> # Example 3: Twins-2-1 left postcentral pial surface -- NO decimation:
    >>> # (zernike_moments took 142 seconds for order = 3 with no decimation)
    >>> import os
    >>> from mindboggle.mio.vtks import read_vtk
    >>> from mindboggle.guts.mesh import remove_faces
    >>> from mindboggle.shapes.zernike.zernike import zernike_moments
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> label_file = os.path.join(path, 'arno', 'labels', 'lh.labels.DKT31.manual.vtk')
    >>> faces, u1,u2, points, u3, labels, u4,u5 = read_vtk(label_file)
    >>> I22 = [i for i,x in enumerate(labels) if x==22] # postcentral
    >>> faces = remove_faces(faces, I22)
    >>> order = 3
    >>> scale_input = True
    >>> zernike_moments(points, faces, order, scale_input)
     [0.005558794553842859,
     0.009838755429501177,
     0.003512500896236744,
     0.00899042745665395,
     0.001672289910738449,
     0.000919469614081582]
    >>> # Example 5: left postcentral + pars triangularis pial surfaces:
    >>> import os
    >>> from mindboggle.mio.vtks import read_vtk, write_vtk
    >>> from mindboggle.guts.mesh import remove_faces
    >>> from mindboggle.shapes.zernike.zernike import zernike_moments
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> label_file = os.path.join(path, 'arno', 'labels', 'lh.labels.DKT31.manual.vtk')
    >>> faces, u1,u2, points, u3, labels, u4,u5 = read_vtk(label_file)
    >>> I20 = [i for i,x in enumerate(labels) if x==20] # pars triangularis
    >>> I22 = [i for i,x in enumerate(labels) if x==22] # postcentral
    >>> I22.extend(I20)
    >>> faces = remove_faces(faces, I22)
    >>> order = 3
    >>> scale_input = True
    >>> zernike_moments(points, faces, order, scale_input)
    [0.006591540793309832,
     0.010749937070447451,
     0.0034900573103799214,
     0.008972460360983864,
     0.0018220183025464518,
     0.0016893113500293917]
    >>> # View both segments:
    >>> from mindboggle.mio.plots import plot_surfaces
    >>> scalars = -1*np.ones(np.shape(labels))
    >>> scalars[I22] = 1
    >>> vtk_file = 'test_two_labels.vtk'
    >>> write_vtk(vtk_file, points, [],[], faces, scalars, scalar_names='scalars', scalar_type='int')
    >>> plot_surfaces(vtk_file)

    """
    import numpy as np

    from mindboggle.guts.mesh import reindex_faces_0to1
    from mindboggle.guts.mesh import decimate
    if pl_cls is None:
        from .pipelines import DefaultPipeline as ZernikePipeline
    else:
        ZernikePipeline = pl_cls

    # Convert 0-indices (Python) to 1-indices (Matlab) for all face indices:
    index1 = False  # already done elsewhere in the code
    if index1:
        faces = reindex_faces_0to1(faces)

    # Convert lists to numpy arrays:
    if isinstance(points, list):
        points = np.array(points)
    if isinstance(faces, list):
        faces = np.array(faces)

    #-------------------------------------------------------------------------
    # Translate all points so that they are centered at their mean,
    # and scale them so that they are bounded by a unit sphere:
    #-------------------------------------------------------------------------
    if scale_input:
        center = np.mean(points, axis=0)
        points = points - center
        maxd = np.max(np.sqrt(np.sum(points**2, axis=1)))
        points = points / maxd

    #-------------------------------------------------------------------------
    # Decimate surface:
    #-------------------------------------------------------------------------
    if 0 < decimate_fraction < 1:
        points, faces, u1,u2 = decimate(points, faces,
            decimate_fraction, decimate_smooth, [], save_vtk=False)

        # Convert lists to numpy arrays:
        points = np.array(points)
        faces = np.array(faces)

    #-------------------------------------------------------------------------
    # Multiprocessor pipeline:
    #-------------------------------------------------------------------------
    pl = ZernikePipeline()

    #-------------------------------------------------------------------------
    # Geometric moments:
    #-------------------------------------------------------------------------
    G = pl.geometric_moments_exact(points, faces, order)

    #
    Z = pl.zernike(G, order)

    #-------------------------------------------------------------------------
    # Extract Zernike descriptors:
    #-------------------------------------------------------------------------
    descriptors = pl.feature_extraction(Z, order).tolist()

    return descriptors
Exemplo n.º 5
0
def zernike_moments(points, faces, order=10, scale_input=True,
                    decimate_fraction=0, decimate_smooth=0, verbose=False):
    """
    Compute the Zernike moments of a surface patch of points and faces.

    Optionally decimate the input mesh.

    Note::
      Decimation sometimes leads to an error of "Segmentation fault: 11"
      (Twins-2-1 left label 14 gives such an error only when decimated.)

    Parameters
    ----------
    points : list of lists of 3 floats
        x,y,z coordinates for each vertex
    faces : list of lists of 3 integers
        each list contains indices to vertices that form a triangle on a mesh
    order : integer
        order of the moments being calculated
    scale_input : bool
        translate and scale each object so it is bounded by a unit sphere?
        (this is the expected input to zernike_moments())
    decimate_fraction : float
        fraction of mesh faces to remove for decimation (0 for no decimation)
    decimate_smooth : integer
        number of smoothing steps for decimation
    verbose : bool
        print statements?

    Returns
    -------
    descriptors : list of floats
        Zernike descriptors

    """
    import numpy as np

    from mindboggle.guts.mesh import reindex_faces_0to1
    from mindboggle.guts.mesh import decimate
    from mindboggle.shapes.zernike.pipelines import DefaultPipeline as Pipeline

    # Convert 0-indices (Python) to 1-indices (Matlab) for all face indices:
    index1 = False  # already done elsewhere in the code
    if index1:
        faces = reindex_faces_0to1(faces)

    # Convert lists to numpy arrays:
    if isinstance(points, list):
        points = np.array(points)
    if isinstance(faces, list):
        faces = np.array(faces)

    # ------------------------------------------------------------------------
    # Translate all points so that they are centered at their mean,
    # and scale them so that they are bounded by a unit sphere:
    # ------------------------------------------------------------------------
    if scale_input:
        center = np.mean(points, axis=0)
        points = points - center
        maxd = np.max(np.sqrt(np.sum(points ** 2, axis=1)))
        points /= maxd

    # ------------------------------------------------------------------------
    # Decimate surface:
    # ------------------------------------------------------------------------
    if 0 < decimate_fraction < 1:
        points, faces, u1, u2 = decimate(points, faces,
                                         decimate_fraction, decimate_smooth, [], save_vtk=False)

        # Convert lists to numpy arrays:
        points = np.array(points)
        faces = np.array(faces)

    # ------------------------------------------------------------------------
    # Multiprocessor pipeline:
    # ------------------------------------------------------------------------
    pl = Pipeline()

    # ------------------------------------------------------------------------
    # Geometric moments:
    # ------------------------------------------------------------------------
    G = pl.geometric_moments_exact(points, faces, order)

    # ------------------------------------------------------------------------
    # ------------------------------------------------------------------------
    Z = pl.zernike(G, order)

    # ------------------------------------------------------------------------
    # Extract Zernike descriptors:
    # ------------------------------------------------------------------------
    descriptors = pl.feature_extraction(Z, order).tolist()

    if verbose:
        print("Zernike moments: {0}".format(descriptors))

    return descriptors