Source code for cbi_toolbox.simu.texture

"""
The texture module allows to generate 3D textures for synthetic samples
"""

# Copyright (c) 2020 Idiap Research Institute, http://www.idiap.ch/
# Written by François Marelli <francois.marelli@idiap.ch>
#
# This file is part of CBI Toolbox.
#
# CBI Toolbox is free software: you can redistribute it and/or modify
# it under the terms of the 3-Clause BSD License.
#
# CBI Toolbox is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# 3-Clause BSD License for more details.
#
# You should have received a copy of the 3-Clause BSD License along
# with CBI Toolbox. If not, see https://opensource.org/licenses/BSD-3-Clause.
#
# SPDX-License-Identifier: BSD-3-Clause

import numpy as np
import noise
from cbi_toolbox.simu import primitives


[docs]def spheres(size, density=1, seed=None): """ Generates a texture full of hollow spheres Parameters ---------- size : int size of the texture density : int, optional spheres density in the texture, by default seed : int, optional seed of the rng, default is None Returns ------- array [size, size, size] the texture """ dtype = np.float32 n_spheres = int(density * 10000) max_radius = int(0.1 * size) min_radius = int(0.02 * size) max_in_radius = 0.5 min_intens = 0.05 max_intens = 0.2 pad_size = size + 4 * max_radius volume = np.ones((pad_size, pad_size, pad_size), dtype=dtype) rng = np.random.default_rng(seed) for _ in range(n_spheres): center = (rng.random(3) * (size + 2 * max_radius) ).astype(int) + max_radius radius = int(rng.uniform(min_radius, max_radius)) in_radius = rng.uniform(0, max_in_radius) intens = rng.uniform(min_intens, max_intens) obj = primitives.ball(radius * 2, in_radius=in_radius, dtype=dtype) volume[center[0] - radius:center[0] + radius, center[1] - radius:center[1] + radius, center[2] - radius:center[2] + radius] *= (1 - obj * intens) return 1 - volume[volume.ndim * [slice(2*max_radius, -2*max_radius)]]
[docs]def simplex(size, scale=1, octaves=3, persistence=0.7, lacunarity=3.5, seed=None): """ Generates 3D simplex noise Parameters ---------- size : int size of the texture scale : int, optional scale of the noise, by default 1 octaves : int, optional number of octaves used, by default 3 persistence : float, optional relative amplitude of octaves, by default 0.7 lacunarity : float, optional relative frequency of octaves, by default 3.5 seed : int, optional seed for the noise, by default None Returns ------- array [size, size, size] the texture """ if seed is None: seed = int(np.random.default_rng().integers(2**10) * scale) volume = np.empty((size, size, size), dtype=np.float32) scale /= size # TODO optimize loops for x in range(size): for y in range(size): for z in range(size): sample = noise.snoise3(seed + x*scale, seed + y*scale, seed + z*scale, octaves=octaves, persistence=persistence, lacunarity=lacunarity) volume[x, y, z] = sample return volume
if __name__ == '__main__': import napari TEST_SIZE = 128 s_spheres = spheres(TEST_SIZE) s_simplex = simplex(TEST_SIZE) phantom = primitives.phantom(TEST_SIZE) * (s_simplex * 0.5 + 0.75) with napari.gui_qt(): viewer = napari.view_image(s_spheres) viewer.add_image(s_simplex) viewer.add_image(phantom)