fractal_noise
¶
This function wraps the pyfastnoisesimd package. The PoreSpy wrapper offers a slightly simpler experience which is more consistent with the function-based approach found in PoreSpy, scikit-image, and scipy.ndimage. For full control over it’s features you can just use it directly since it is installed with PoreSpy.
import matplotlib.pyplot as plt
import porespy as ps
import numpy as np
import inspect
inspect.signature(ps.generators.fractal_noise)
<Signature (shape, porosity: float = None, frequency: float = 0.05, octaves: int = 4, gain: float = 0.5, mode: Literal['simplex', 'perlin', 'value', 'cubic'] = 'simplex', seed: int = None, cores: int = 1, uniform: bool = True)>
np.random.seed(10)
shape = [200, 200]
im = ps.generators.fractal_noise(shape=shape)
fig, ax = plt.subplots(1, 1, figsize=[4, 4])
ax.imshow(im, origin='lower', interpolation='none')
ax.axis(False);
cores
¶
The noise is generated by the pyfastnoisesimd
package which supports multiple cores to really speed things up. By default we use all the available cores on the machine, however, occasionally this causes problems and kernel crashes. Setting this argument to a value less than the maximum usually avoids these issues. Here we’ll use 1.
cores = 1
im = ps.generators.fractal_noise(shape=shape, cores=cores)
fig, ax = plt.subplots(1, 1, figsize=[4, 4])
ax.imshow(im, origin='lower', interpolation='none')
ax.axis(False);
seed
¶
In order to produce the same image twice it’s possible send a seed value to the function. Unfortunately the numpy.random.seed
function is not recognized:
seed = 0
im1 = ps.generators.fractal_noise(shape=shape, seed=seed, cores=cores)
im2 = ps.generators.fractal_noise(shape=shape, seed=seed, cores=cores)
seed = 1
im3 = ps.generators.fractal_noise(shape=shape, seed=seed, cores=cores)
fig, ax = plt.subplots(1, 3, figsize=[9, 3])
ax[0].imshow(im1, origin='lower', interpolation='none')
ax[1].imshow(im2, origin='lower', interpolation='none')
ax[2].imshow(im3, origin='lower', interpolation='none')
ax[0].axis(False)
ax[1].axis(False)
ax[2].axis(False)
ax[0].set_title('seed = 0')
ax[1].set_title('seed = 0')
ax[2].set_title('seed = 1');
frequency
¶
This controls the size of the blobs relative to the image size, with larger values giving smaller features:
fig, ax = plt.subplots(1, 2, figsize=[8, 4])
frequency = 0.1
im1 = ps.generators.fractal_noise(shape=shape, frequency=frequency, cores=cores, seed=seed)
ax[0].imshow(im)
ax[0].axis(False)
ax[0].set_title(f'frequency = 0.05')
frequency = 0.05
im2 = ps.generators.fractal_noise(shape=shape, frequency=frequency, cores=cores, seed=seed)
ax[1].imshow(im2)
ax[1].axis(False)
ax[1].set_title(f'frequency = 0.1');
octaves
¶
The numbers of octaves controls the levels of noise that get overlaid to create the realistic texture
fig, ax = plt.subplots(1, 2, figsize=[8, 4])
octaves=2
im1 = ps.generators.fractal_noise(shape=shape, octaves=octaves, frequency=frequency, seed=seed, cores=cores)
ax[0].imshow(im1)
ax[0].axis(False)
ax[0].set_title(f'octaves = {octaves}')
octaves=10
im2 = ps.generators.fractal_noise(shape=shape, octaves=octaves, frequency=frequency, seed=seed, cores=cores)
ax[1].imshow(im2)
ax[1].axis(False)
ax[1].set_title(f'octaves = {octaves}');
gain
¶
This controls the intensity of each added layer of noise:
fig, ax = plt.subplots(1, 2, figsize=[8, 4])
gain = 0.8
im1 = ps.generators.fractal_noise(shape=shape, gain=gain, seed=seed, cores=cores)
ax[0].imshow(im1)
ax[0].axis(False)
ax[0].set_title(f'gain = {gain}')
gain = 0.5
im2 = ps.generators.fractal_noise(shape=shape, gain=gain, seed=seed, cores=cores)
ax[1].imshow(im2)
ax[1].axis(False)
ax[1].set_title(f'gain = {gain}');
mode
¶
The pyfastnoisesimd
package provides 4 different methods for computing noise, which we expose via the mode
argument:
fig, ax = plt.subplots(2, 2, figsize=[8, 8])
mode='perlin'
im1 = ps.generators.fractal_noise(shape=shape, gain=gain, seed=seed, cores=cores, mode=mode)
ax[0][0].imshow(im1)
ax[0][0].axis(False)
ax[0][0].set_title(f'mode = {mode}')
mode = 'simplex'
im2 = ps.generators.fractal_noise(shape=shape, gain=gain, seed=seed, cores=cores, mode=mode)
ax[0][1].imshow(im2)
ax[0][1].axis(False)
ax[0][1].set_title(f'mode = {mode}')
mode = 'cubic'
im2 = ps.generators.fractal_noise(shape=shape, gain=gain, seed=seed, cores=cores, mode=mode)
ax[1][0].imshow(im2)
ax[1][0].axis(False)
ax[1][0].set_title(f'mode = {mode}')
mode = 'value'
im2 = ps.generators.fractal_noise(shape=shape, gain=gain, seed=seed, cores=cores, mode=mode)
ax[1][1].imshow(im2)
ax[1][1].axis(False)
ax[1][1].set_title(f'mode = {mode}');
uniform
and porosity
¶
uniform
Controls whether the returned noise values are scaled to a uniform distribution, which is useful for thresholding to create a specific porosity, or if the original distribution is returned.
fig, ax = plt.subplots(2, 2, figsize=[8, 8])
mode='perlin'
uniform=True
im1 = ps.generators.fractal_noise(shape=shape, gain=gain, seed=seed, cores=cores, mode=mode, uniform=uniform)
ax[0][0].imshow(im1)
ax[0][0].axis(False)
ax[0][0].set_title(f'uniform = {uniform}')
uniform=False
im2 = ps.generators.fractal_noise(shape=shape, gain=gain, seed=seed, cores=cores, mode=mode, uniform=uniform)
ax[0][1].imshow(im2)
ax[0][1].axis(False)
ax[0][1].set_title(f'uniform = {uniform}')
ax[1][0].hist(im1.flatten())
ax[1][1].hist(im2.flatten());
porosity
can be specified for a specific porosity level. The image is thresholded after being converted into a uniform distribution. In this case, uniform
does not need to be specified to True
.
fig, ax = plt.subplots(1, 2, figsize=[8, 4])
porosity1=0.3
im1 = ps.generators.fractal_noise(shape=shape, porosity=porosity1, gain=gain, seed=seed, cores=cores, mode=mode)
ax[0].imshow(im1)
ax[0].axis(False)
ax[0].set_title(f'porosity = {porosity1}')
porosity2=0.6
im2 = ps.generators.fractal_noise(shape=shape, porosity=porosity2, gain=gain, seed=seed, cores=cores, mode=mode)
ax[1].imshow(im2)
ax[1].axis(False)
ax[1].set_title(f'porosity = {porosity2}');