コード例 #1
0
 def _plot_Sphere(self, os, **kwargs) -> Iterator[Artist]:
     from trimesh.creation import icosphere
     kwargs.setdefault('alpha', 0.5)
     ret = []
     for o in os:
         tmesh = icosphere(radius=abs(o.radius))
         loc = self._as_point_tuple_3d(o.location)
         t = Triangulation(loc[0] + tmesh.vertices[:, 0],
                           loc[1] + tmesh.vertices[:, 1],
                           triangles=tmesh.faces)
         yield self._ax.plot_trisurf(t, loc[2] + tmesh.vertices[:, 2],
                                     **kwargs)
コード例 #2
0
ファイル: generator.py プロジェクト: menezesandre/stackrl
def irregular(
    subdivisions=2,
    radius=0.0625,
    factor=0.1,
    seed=None,
):
    """Generates a mesh from an icosphere, by applying some randomly
    parametrized transformations.

  Args:
    subdivisions: subdivisions parameter of the icosphere
    radius: the mesh always fits within a sphere of this radius.
    factor: ratio of the maximum radius that corresponds to the 
      mode distance from vertice to center. A smaller factor allows
      greater irregularity.
    seed: seed for the random number generator, or generator to be 
      used. 
  """
    random = np.random.default_rng(seed)
    # Create icosphere mesh with max radius and given subdivisions
    mesh = creation.icosphere(
        subdivisions=subdivisions,
        radius=factor * radius,
    )
    # Apply random vertex displacement in normal direction
    mesh.vertices += random.triangular(
        -factor * radius, 0, (1 - factor) * radius,
        (len(mesh.vertices), 1)) * mesh.vertex_normals
    # Get the convex hull
    mesh = mesh.convex_hull
    # pylint: disable=no-member

    # Align the minimum volume bounding box
    mesh.apply_obb()

    # Apply a random scaling in the direction of the smallest extent of
    # the bounding box. The scalling is only applied if the ratio between
    # smallest and largest extents is greater than factor.
    extents = mesh.bounding_box.extents
    direction = tuple(int(i == np.argmin(extents)) for i in range(3))
    ratio = min(extents) / max(extents)
    if ratio > factor:
        mesh.apply_transform(
            transformations.scale_matrix(
                factor=random.triangular(
                    factor / ratio,
                    1.,  # min(1., max(0.5, factor)/ratio),
                    1.,
                ),
                # factor=random.uniform(factor/ratio, 1.),
                direction=direction,
            ))
    return mesh
コード例 #3
0
def generate_sphere_icosahedron(subdivisions=3, radius=1.0):
    """
    generate a sphere by subdividing an icosahedron
    simply call the trimesh function
    see trimesh.creation.icosphere for more details
    :param subdivisions:  int
      How many times to subdivide the mesh.
      Note that the number of faces will grow as function of
      4 ** subdivisions, so you probably want to keep this under ~5
    :param radius: float
      Desired radius of sphere
    :return:
    """
    return tcr.icosphere(subdivisions=subdivisions, radius=radius)
コード例 #4
0
ファイル: reconstruct.py プロジェクト: peterspackman/chmpy
def reconstructed_surface_icosphere(coefficients, real=True, subdivisions=3):
    if real:
        n = len(coefficients)
        l_max = int((-3 + np.sqrt(8 * n + 1)) // 2)
    else:
        raise NotImplementedError(
            "Complex reconstructed surface case not yet implemented")
    LOG.debug("Reconstructing deduced l_max = %d", l_max)
    sht = SHT(l_max)

    from trimesh.creation import icosphere

    sphere = icosphere(subdivisions=subdivisions)
    theta = np.arccos(sphere.vertices[:, 2])
    phi = np.arctan2(sphere.vertices[:, 1], sphere.vertices[:, 0])
    r = np.empty_like(phi)
    for i in range(phi.shape[0]):
        r[i] = sht.evaluate_at_points(coefficients, theta[i], phi[i])
    sphere.vertices *= r[:, np.newaxis]
    return sphere
コード例 #5
0
def getLBP3DImage(inputImage, inputMask, **kwargs):
  """
  Compute and return the Local Binary Pattern (LBP) in 3D using spherical harmonics.
  If ``force2D`` is set to true (= feature extraction in 2D) a warning is logged.

  LBP is only calculated for voxels segmented in the mask

  Following settings are possible:

    - ``lbp3DLevels`` [2]: integer, specifies the the number of levels in spherical harmonics to use.
    - ``lbp3DIcosphereRadius`` [1]: Float, specifies the radius in which the neighbours should be sampled
    - ``lbp3DIcosphereSubdivision`` [1]: Integer, specifies the number of subdivisions to apply in the icosphere

  :return: Yields LBP filtered image for each level, 'lbp-3D-m<level>' and ``kwargs`` (customized settings).
           Additionally yields the kurtosis image, 'lbp-3D-k' and ``kwargs``.

  .. note::
    LBP can often return only a very small number of different gray levels. A customized bin width is often needed.
  .. warning::
    Requires package ``scipy`` and ``trimesh`` to function. If not available, this filter logs a warning and does not
    yield an image.

  References:

  - Banerjee, J, Moelker, A, Niessen, W.J, & van Walsum, T.W. (2013), "3D LBP-based rotationally invariant region
    description." In: Park JI., Kim J. (eds) Computer Vision - ACCV 2012 Workshops. ACCV 2012. Lecture Notes in Computer
    Science, vol 7728. Springer, Berlin, Heidelberg. doi:10.1007/978-3-642-37410-4_3
  """
  global logger
  try:
    from scipy.stats import kurtosis
    from scipy.ndimage.interpolation import map_coordinates
    from scipy.special import sph_harm
    from trimesh.creation import icosphere
  except ImportError:
    logger.warning('Could not load required package "scipy" or "trimesh", cannot implement filter LBP 3D')
    return

  # Warn the user if features are extracted in 2D, as this function calculates LBP in 3D
  if kwargs.get('force2D', False):
    logger.warning('Calculating Local Binary Pattern in 3D, but extracting features in 2D. Use with caution!')

  label = kwargs.get('label', 1)

  lbp_levels = kwargs.get('lbp3DLevels', 2)
  lbp_icosphereRadius = kwargs.get('lbp3DIcosphereRadius', 1)
  lbp_icosphereSubdivision = kwargs.get('lbp3DIcosphereSubdivision', 1)

  im_arr = sitk.GetArrayFromImage(inputImage)
  ma_arr = sitk.GetArrayFromImage(inputMask)

  # Variables used in the shape comments:
  # Np Number of voxels
  # Nv Number of vertices

  # Vertices icosahedron for spherical sampling
  coords_icosahedron = numpy.array(icosphere(lbp_icosphereSubdivision, lbp_icosphereRadius).vertices)  # shape(Nv, 3)

  # Corresponding polar coordinates
  theta = numpy.arccos(numpy.true_divide(coords_icosahedron[:, 2], lbp_icosphereRadius))
  phi = numpy.arctan2(coords_icosahedron[:, 1], coords_icosahedron[:, 0])

  # Corresponding spherical harmonics coefficients Y_{m, n, theta, phi}
  Y = sph_harm(0, 0, theta, phi)  # shape(Nv,)
  n_ix = numpy.array(0)

  for n in range(1, lbp_levels):
    for m in range(-n, n + 1):
      n_ix = numpy.append(n_ix, n)
      Y = numpy.column_stack((Y, sph_harm(m, n, theta, phi)))
  # shape (Nv, x) where x is the number of iterations in the above loops + 1

  # Get labelled coordinates
  ROI_coords = numpy.where(ma_arr == label)  # shape(3, Np)

  # Interpolate f (samples on the spheres across the entire volume)
  coords = numpy.array(ROI_coords).T[None, :, :] + coords_icosahedron[:, None, :]  # shape(Nv, Np, 3)
  f = map_coordinates(im_arr, coords.T, order=3)  # Shape(Np, Nv)  Note that 'Np' and 'Nv' are swapped due to .T

  # Compute spherical Kurtosis
  k = kurtosis(f, axis=1)  # shape(Np,)

  # Apply sign function
  f_centroids = im_arr[ROI_coords]  # Shape(Np,)
  f = numpy.greater_equal(f, f_centroids[:, None]).astype(int)  # Shape(Np, Nv)

  # Compute c_{m,n} coefficients
  c = numpy.multiply(f[:, :, None], Y[None, :, :])  # Shape(Np, Nv, x)
  c = c.sum(axis=1)  # Shape(Np, x)

  # Integrate over m
  f = numpy.multiply(c[:, None, n_ix == 0], Y[None, :, n_ix == 0])  # Shape (Np, Nv, 1)
  for n in range(1, lbp_levels):
    f = numpy.concatenate((f,
                           numpy.sum(numpy.multiply(c[:, None, n_ix == n], Y[None, :, n_ix == n]),
                                     axis=2, keepdims=True)
                           ),
                          axis=2)
  # Shape f (Np, Nv, levels)

  # Compute L2-Norm
  f = numpy.sqrt(numpy.sum(f ** 2, axis=1))  # shape(Np, levels)

  # Keep only Real Part
  f = numpy.real(f)  # shape(Np, levels)
  k = numpy.real(k)  # shape(Np,)

  # Yield the derived images for each level
  result = numpy.ndarray(im_arr.shape)
  for l_idx in range(lbp_levels):
    result[ROI_coords] = f[:, l_idx]

    # Create a SimpleITK image
    im = sitk.GetImageFromArray(result)
    im.CopyInformation(inputImage)

    yield im, 'lbp-3D-m%d' % (l_idx + 1), kwargs

  # Yield Kurtosis
  result[ROI_coords] = k

  # Create a SimpleITK image
  im = sitk.GetImageFromArray(result)
  im.CopyInformation(inputImage)

  yield im, 'lbp-3D-k', kwargs
コード例 #6
0
import numpy as np
import matplotlib.pyplot as plt
from mayavi import mlab
import trimesh

from bfieldtools.suhtools import SuhBasis
from bfieldtools.utils import find_mesh_boundaries

from trimesh.creation import icosphere
from bfieldtools.utils import load_example_mesh

# Import meshes

# Sphere
sphere = icosphere(4, 0.1)

# Plane mesh centered on the origin
plane = load_example_mesh("10x10_plane_hires")
scaling_factor = 0.02
plane.apply_scale(scaling_factor)
# Rotate to x-plane
t = np.eye(4)
t[1:3, 1:3] = np.array([[0, 1], [-1, 0]])
plane.apply_transform(t)

# Bunny
bunny = load_example_mesh("bunny_repaired")
bunny.vertices -= bunny.vertices.mean(axis=0)

mlab.figure(bgcolor=(1, 1, 1))
コード例 #7
0
def _get_node_sphere(node, radius=0.5):
    sp = icosphere(subdivisions=2)
    sp.apply_scale(radius)
    sp.apply_translation(node)
    return sp
コード例 #8
0
)
from bfieldtools.mesh_magnetics import scalar_potential_coupling as compute_U
from bfieldtools.mesh_impedance import mutual_inductance_matrix
from bfieldtools.contour import scalar_contour
from bfieldtools import sphtools
from bfieldtools.utils import load_example_mesh
from bfieldtools.mesh_calculus import mass_matrix

# domain = 'sphere'
# domain = 'cube'
domain = "combined"

if domain == "sphere":
    from trimesh.creation import icosphere

    mesh1 = icosphere(3, 0.65)
    mesh2 = icosphere(3, 0.8)
elif domain == "cube":
    from trimesh.creation import box
    from trimesh.smoothing import filter_laplacian

    mesh1 = box((1.0, 1.0, 1.0))
    mesh2 = box((1.5, 1.5, 1.5))

    for i in range(4):
        mesh1 = mesh1.subdivide()
        mesh2 = mesh2.subdivide()

    mesh1 = filter_laplacian(mesh1)
    mesh2 = filter_laplacian(mesh2, 0.9)
elif domain == "combined":