示例#1
0
def leave_feeding_trace(x,
                        y,
                        shape,
                        trace_strength=1.0,
                        sigma=7,
                        mode="wrap",
                        wrap_around=True,
                        truncate=4):
    """Turns x,y-coordinates returned by a list of calls to init-functions into a smooth feeding array."""
    base = np.zeros(shape)
    if wrap_around == True:
        x = x % shape[0]
        y = y % shape[1]
    else:
        print("CutOff overly large x and y: Not yet implemented.")

    base[np.floor(x % (base.shape[0])).astype(int),
         np.floor(y % (base.shape[1])).astype(int), ] = trace_strength
    base = gaussian_filter(base, sigma=sigma, mode=mode, truncate=truncate)
    return base
示例#2
0
 def diffuse_gaussian(self, sigma=7, mode="wrap", truncate=4):
     """Pheromones get distributed using gaussian smoothing."""
     self.trail_map = gaussian_filter(self.trail_map,
                                      sigma=sigma,
                                      mode=mode,
                                      truncate=truncate)
示例#3
0
文件: scalespace.py 项目: dipy/cudipy
    def __init__(self,
                 image,
                 factors,
                 sigmas,
                 image_grid2world=None,
                 input_spacing=None,
                 mask0=False):
        """ IsotropicScaleSpace

        Computes the Scale Space representation of an image using isotropic
        smoothing kernels for all scales. The scale space is simply a list
        of images produced by smoothing the input image with a Gaussian
        kernel with different smoothing parameters.

        This specialization of ScaleSpace allows the user to provide custom
        scale and smoothing factors for all scales.

        Parameters
        ----------
        image : array, shape (r,c) or (s, r, c) where s is the number of
            slices, r is the number of rows and c is the number of columns of
            the input image.
        factors : list of floats
            custom scale factors to build the scale space (one factor for each
            scale).
        sigmas : list of floats
            custom smoothing parameter to build the scale space (one parameter
            for each scale).
        image_grid2world : array, shape (dim + 1, dim + 1), optional
            the grid-to-space transform of the image grid. The default is
            the identity matrix.
        input_spacing : array, shape (dim,), optional
            the spacing (voxel size) between voxels in physical space. The
            default if 1.0 along all axes.
        mask0 : Boolean, optional
            if True, all smoothed images will be zero at all voxels that are
            zero in the input image. The default is False.
        """
        self.dim = len(image.shape)
        self.num_levels = len(factors)
        if len(sigmas) != self.num_levels:
            raise ValueError("sigmas and factors must have the same length")
        input_size = np.array(image.shape)
        if mask0:
            mask = cp.asarray(image > 0, dtype=np.int32)

        # Normalize input image to [0,1]
        img = (image.astype(cp.float64) - image.min()) / cp.ptp(image)
        if mask0:
            img *= mask

        # The properties are saved in separate lists. Insert input image
        # properties at the first level of the scale space
        self.images = [img.astype(floating)]
        self.domain_shapes = [input_size.astype(np.int32)]
        if input_spacing is None:
            input_spacing = np.ones((self.dim, ), dtype=np.int32)
        elif isinstance(input_spacing, cp.ndarray):
            input_spacing = cp.asnumpy(input_spacing)
        self.spacings = [input_spacing]
        self.scalings = [np.ones(self.dim)]
        self.sigmas = [np.ones(self.dim) * sigmas[self.num_levels - 1]]

        if image_grid2world is not None:
            if isinstance(image_grid2world, cp.ndarray):
                image_grid2world = cp.asnumpy(image_grid2world)
            self.affines = [image_grid2world]
            self.affine_invs = [np.linalg.inv(image_grid2world)]
        else:
            self.affines = [None]
            self.affine_invs = [None]

        # Compute the rest of the levels
        min_index = np.argmin(input_spacing)
        for i in range(1, self.num_levels):
            factor = factors[self.num_levels - 1 - i]
            shrink_factors = np.zeros(self.dim)
            new_spacing = np.zeros(self.dim)
            shrink_factors[min_index] = factor
            new_spacing[min_index] = input_spacing[min_index] * factor
            for j in range(self.dim):
                if j != min_index:
                    # Select the factor that maximizes isotropy
                    shrink_factors[j] = factor
                    new_spacing[j] = input_spacing[j] * factor
                    min_diff = np.abs(new_spacing[j] - new_spacing[min_index])
                    for f in range(1, factor):
                        diff = input_spacing[j] * f - new_spacing[min_index]
                        diff = np.abs(diff)
                        if diff < min_diff:
                            shrink_factors[j] = f
                            new_spacing[j] = input_spacing[j] * f
                            min_diff = diff

            extended = np.append(shrink_factors, [1])
            if image_grid2world is not None:
                affine = image_grid2world.dot(np.diag(extended))
            else:
                affine = np.diag(extended)
            output_size = (input_size / shrink_factors).astype(np.int32)
            new_sigmas = np.ones(self.dim) * sigmas[self.num_levels - i - 1]

            # Filter along each direction with the appropriate sigma
            filtered = filters.gaussian_filter(image.astype(np.float64),
                                               new_sigmas)
            filtered = (filtered.astype(np.float64) -
                        filtered.min()) / cp.ptp(filtered)
            if mask0:
                filtered *= mask

            # Add current level to the scale space
            self.images.append(filtered.astype(floating))
            self.domain_shapes.append(output_size)
            self.spacings.append(new_spacing)
            self.scalings.append(shrink_factors)
            self.affines.append(affine)
            self.affine_invs.append(np.linalg.inv(affine))
            self.sigmas.append(new_sigmas)
示例#4
0
def structure_tensor_3d(volume, sigma, rho, out=None):
    """Structure tensor for 3D image data.

    Arguments:
        volume: array_like
            A 3D array. Pass cupy.ndarray to avoid copying volume.
        sigma: scalar
            A noise scale, structures smaller than sigma will be removed by smoothing.
        rho: scalar
            An integration scale giving the size over the neighborhood in which the
            orientation is to be analysed.
        out: cupy.ndarray, optional
            An array with the shape ``(6, volume.shape)`` in which to place the output.

    Returns:
        S: cupy.ndarray
            An array with shape ``(6, volume.shape)`` containing elements of structure tensor
            (s_xx, s_yy, s_zz, s_xy, s_xz, s_yz).

    Authors: [email protected], 2019; [email protected], 2019-2020
    """

    # Make sure it's a Numpy array.
    volume = np.asarray(volume)

    # Computing derivatives (scipy implementation truncates filter at 4 sigma).
    Vx = filters.gaussian_filter(volume,
                                 sigma,
                                 order=[0, 0, 1],
                                 mode='nearest')
    Vy = filters.gaussian_filter(volume,
                                 sigma,
                                 order=[0, 1, 0],
                                 mode='nearest')
    Vz = filters.gaussian_filter(volume,
                                 sigma,
                                 order=[1, 0, 0],
                                 mode='nearest')

    if out is None:
        # Allocate S.
        S = np.empty((6, ) + volume.shape, dtype=volume.dtype)
    else:
        # S is already allocated. We assume the size is correct.
        S = out

    # Integrating elements of structure tensor (scipy uses sequence of 1D).
    tmp = np.empty(volume.shape, dtype=volume.dtype)
    np.multiply(Vx, Vx, out=tmp)
    filters.gaussian_filter(tmp, rho, mode='nearest', output=S[0])
    np.multiply(Vy, Vy, out=tmp)
    filters.gaussian_filter(tmp, rho, mode='nearest', output=S[1])
    np.multiply(Vz, Vz, out=tmp)
    filters.gaussian_filter(tmp, rho, mode='nearest', output=S[2])
    np.multiply(Vx, Vy, out=tmp)
    filters.gaussian_filter(tmp, rho, mode='nearest', output=S[3])
    np.multiply(Vx, Vz, out=tmp)
    filters.gaussian_filter(tmp, rho, mode='nearest', output=S[4])
    np.multiply(Vy, Vz, out=tmp)
    filters.gaussian_filter(tmp, rho, mode='nearest', output=S[5])

    return S
示例#5
0
文件: scalespace.py 项目: dipy/cudipy
    def __init__(self,
                 image,
                 num_levels,
                 image_grid2world=None,
                 input_spacing=None,
                 sigma_factor=0.2,
                 mask0=False):
        """ ScaleSpace

        Computes the Scale Space representation of an image. The scale space is
        simply a list of images produced by smoothing the input image with a
        Gaussian kernel with increasing smoothing parameter. If the image's
        voxels are isotropic, the smoothing will be the same along all
        directions: at level L = 0, 1, ..., the sigma is given by
        $s * ( 2^L - 1 )$.
        If the voxel dimensions are not isotropic, then the smoothing is
        weaker along low resolution directions.

        Parameters
        ----------
        image : array, shape (r,c) or (s, r, c) where s is the number of
            slices, r is the number of rows and c is the number of columns of
            the input image.
        num_levels : int
            the desired number of levels (resolutions) of the scale space
        image_grid2world : array, shape (dim + 1, dim + 1), optional
            the grid-to-space transform of the image grid. The default is
            the identity matrix
        input_spacing : array, shape (dim,), optional
            the spacing (voxel size) between voxels in physical space. The
            default is 1.0 along all axes
        sigma_factor : float, optional
            the smoothing factor to be used in the construction of the scale
            space. The default is 0.2
        mask0 : Boolean, optional
            if True, all smoothed images will be zero at all voxels that are
            zero in the input image. The default is False.

        """
        self.dim = len(image.shape)
        self.num_levels = num_levels
        input_size = np.array(image.shape)
        if mask0:
            mask = cp.asarray(image > 0, dtype=np.int32)

        # Normalize input image to [0,1]
        img = (image - image.min()) / cp.ptp(image)
        if mask0:
            img *= mask

        # The properties are saved in separate lists. Insert input image
        # properties at the first level of the scale space
        self.images = [img.astype(floating)]
        self.domain_shapes = [input_size.astype(np.int32)]
        # Note: Keep small arrays like spacings, scalings, sigmas on
        #       the host.
        if input_spacing is None:
            input_spacing = np.ones((self.dim, ), dtype=np.int32)
        elif isinstance(input_spacing, cp.ndarray):
            input_spacing = cp.asnumpy(input_spacing)
        self.spacings = [input_spacing]
        self.scalings = [np.ones(self.dim)]
        self.sigmas = [np.zeros(self.dim)]
        # also keep affines on the host for now
        if image_grid2world is not None:
            if isinstance(image_grid2world, cp.ndarray):
                image_grid2world = cp.asnumpy(image_grid2world)
            self.affines = [image_grid2world]
            self.affine_invs = [np.linalg.inv(image_grid2world)]
        else:
            self.affines = [None]
            self.affine_invs = [None]

        # Compute the rest of the levels
        min_spacing = cp.min(input_spacing)
        for i in range(1, num_levels):
            scaling_factor = 2**i
            # Note: the minimum below is present in ANTS to prevent the scaling
            # from being too large (making the sub-sampled image to be too
            # small) this makes the sub-sampled image at least 32 voxels at
            # each direction it is risky to make this decision based on image
            # size, though (we need to investigate more the effect of this)

            # scaling = np.minimum(scaling_factor * min_spacing /input_spacing,
            #                     input_size / 32)

            scaling = scaling_factor * min_spacing / input_spacing
            output_spacing = input_spacing * scaling
            extended = np.append(scaling, [1])
            if image_grid2world is not None:
                affine = image_grid2world.dot(np.diag(extended))
            else:
                affine = np.diag(extended)
            output_size = input_size * (input_spacing / output_spacing) + 0.5
            output_size = output_size.astype(np.int32)
            sigmas = sigma_factor * (output_spacing / input_spacing - 1.0)

            # Filter along each direction with the appropriate sigma
            filtered = filters.gaussian_filter(image, sigmas)
            filtered = (filtered - filtered.min()) / cp.ptp(filtered)
            if mask0:
                filtered *= mask

            # Add current level to the scale space
            self.images.append(filtered.astype(floating))
            self.domain_shapes.append(output_size)
            self.spacings.append(output_spacing)
            self.scalings.append(scaling)
            self.affines.append(affine)
            self.affine_invs.append(np.linalg.inv(affine))
            self.sigmas.append(sigmas)