tools¶
Helper Functions
This module contains a variety of functions for manipulating images in ways that do NOT return a modified version of the original image.
porespy.tools.bbox_to_slices (bbox) 
Given a tuple containing bounding box coordinates, return a tuple of slice objects. 
porespy.tools.extend_slice (s, shape[, pad]) 
Adjust slice indices to include additional voxles around the slice. 
porespy.tools.extract_subsection (im, shape) 
Extracts the middle section of a image 
porespy.tools.extract_cylinder (im[, r, axis]) 
Returns a cylindrical section of the image of specified radius. 
porespy.tools.fftmorphology (im, strel[, mode]) 
Perform morphological operations on binary images using fft approach for improved performance 
porespy.tools.find_outer_region (im[, r]) 
Finds regions of the image that are outside of the solid matrix. 
porespy.tools.get_border (shape[, thickness, …]) 
Creates an array of specified size with corners, edges or faces labelled as True. 
porespy.tools.get_planes (im[, squeeze]) 
Extracts three planar images from the volumetric image, one for each principle axis. 
porespy.tools.get_slice (im, center, size[, pad]) 
Given a center location and radius of a feature, returns the slice object into the im that bounds the feature but does not extend beyond the image boundaries. 
porespy.tools.insert_cylinder (im, xyz0, xyz1, r) 
Inserts a cylinder of given radius onto a given image 
porespy.tools.insert_sphere (im, c, r) 
Inserts a sphere of a specified radius into a given image 
porespy.tools.in_hull (points, hull) 
Test if a list of coordinates are inside a given convex hull 
porespy.tools.make_contiguous (im[, keep_zeros]) 
Take an image with arbitrary greyscale values and adjust them to ensure all values fall in a contiguous range starting at 0. 
porespy.tools.mesh_region (region[, strel]) 
Creates a trimesh of the provided region using the marching cubes algorithm 
porespy.tools.norm_to_uniform (im[, scale]) 
Take an image with normally distributed greyscale values and converts it to a uniform (i.e. 
porespy.tools.overlay (im1, im2, c) 
Overlays im2 onto im1 , given voxel coords of center of im2 in im1 . 
porespy.tools.randomize_colors (im[, keep_vals]) 
Takes a greyscale image and randomly shuffles the greyscale values, so that all voxels labeled X will be labelled Y, and all voxels labeled Y will be labeled Z, where X, Y, Z and so on are randomly selected from the values in the input image. 
porespy.tools.subdivide (im[, divs]) 
Returns slices into an image describing the specified number of subarrays. 
porespy.tools.ps_disk (radius) 
Creates circular disk structuring element for morphological operations 
porespy.tools.ps_ball (radius) 
Creates spherical ball structuring element for morphological operations 

porespy.tools.
bbox_to_slices
(bbox)[source]¶ Given a tuple containing bounding box coordinates, return a tuple of slice objects.
A bounding box in the form of a straight list is returned by several functions in skimage, but these cannot be used to direct index into an image. This function returns a tuples of slices can be, such as:
im[bbox_to_slices([xmin, ymin, xmax, ymax])]
.Parameters: bbox (tuple of ints) – The bounding box indices in the form ( xmin
,ymin
,zmin
,xmax
,ymax
,zmax
). For a 2D image, simply omit thezmin
andzmax
entries.Returns: slices – A tuple of slice objects that can be used to directly index into a larger image. Return type: tuple

porespy.tools.
extend_slice
(s, shape, pad=1)[source]¶ Adjust slice indices to include additional voxles around the slice. The key to this function is that is does bounds checking to ensure the indices don’t extend outside the image.
Parameters:  s (list of slice objects) – A list (or tuple) of N slice objects, where N is the number of dimensions in the image.
 shape (array_like) – The shape of the image into which the slice objects apply. This is used to check the bounds to prevent indexing beyond the image.
 pad (int) – The number of voxels to expand in each direction.
Returns: slices – A list slice of objects with the start and stop attributes respectively incremented and decremented by 1, without extending beyond the image boundaries.
Return type: list
Examples
>>> from scipy.ndimage import label, find_objects >>> from porespy.tools import extend_slice >>> im = sp.array([[1, 0, 0], [1, 0, 0], [0, 0, 1]]) >>> labels = label(im)[0] >>> s = find_objects(labels)
Using the slices returned by
find_objects
, set the first label to 3>>> labels[s[0]] = 3 >>> print(labels) [[3 0 0] [3 0 0] [0 0 2]]
Next extend the slice, and use it to set the values to 4
>>> s_ext = extend_slice(s[0], shape=im.shape, pad=1) >>> labels[s_ext] = 4 >>> print(labels) [[4 4 0] [4 4 0] [4 4 2]]
As can be seen by the location of the 4s, the slice was extended by 1, and also handled the extension beyond the boundary correctly.

porespy.tools.
extract_subsection
(im, shape)[source]¶ Extracts the middle section of a image
Parameters:  im (NDarray) – Image from which to extract the subsection
 shape (array_like) – Can either specify the size of the extracted section or the fractional size of the image to extact.
Returns: image – An NDarray of size given by the
shape
argument, taken from the center of the image.Return type: NDarray
Examples
>>> import scipy as sp >>> from porespy.tools import extract_subsection >>> im = sp.array([[1, 1, 1, 1], [1, 2, 2, 2], [1, 2, 3, 3], [1, 2, 3, 4]]) >>> print(im) [[1 1 1 1] [1 2 2 2] [1 2 3 3] [1 2 3 4]] >>> im = extract_subsection(im=im, shape=[2, 2]) >>> print(im) [[2 2] [2 3]]

porespy.tools.
extract_cylinder
(im, r=None, axis=0)[source]¶ Returns a cylindrical section of the image of specified radius.
This is useful for making square images look like cylindrical cores such as those obtained from Xray tomography.
Parameters:  im (NDarray) – The image of the porous material
 r (scalr) – The radius of the cylinder to extract. If none if given then the default is the largest cylinder that can fit inside the xy plane.
 axis (scalar) – The axis along with the cylinder will be oriented.
Returns: image – A copy of
im
with True values indicating the void space but with the sample trimmed to a cylindrical section in the center of the image. The region outside the cylindrical section is labeled withTrue
values since it is open space.Return type: NDarray

porespy.tools.
fftmorphology
(im, strel, mode='opening')[source]¶ Perform morphological operations on binary images using fft approach for improved performance
Parameters:  im (ndarray) – The binary image on which to perform the morphological operation
 strel (ndarray) – The structuring element to use. Must have the same dims as
im
.  mode (string) – The type of operation to perform. Options are ‘dilation’, ‘erosion’, ‘opening’ and ‘closing’.
Returns: image – A copy of the image with the specified moropholgical operation applied using the fftbased methods available in scipy.fftconvolve.
Return type: NDarray
Notes
This function uses
scipy.signal.fftconvolve
which can be more than 10x faster than the standard binary morphology operation inscipy.ndimage
. This speed up may not always be realized, depending on the scipy distribution used.Examples
>>> import porespy as ps >>> from numpy import array_equal >>> import scipy.ndimage as spim >>> from skimage.morphology import disk >>> im = ps.generators.blobs(shape=[100, 100], porosity=0.8)
Check that erosion, dilation, opening, and closing are all the same as the
scipy.ndimage
functions:>>> result = ps.filters.fftmorphology(im, strel=disk(5), mode='erosion') >>> temp = spim.binary_erosion(im, structure=disk(5)) >>> array_equal(result, temp) True
>>> result = ps.filters.fftmorphology(im, strel=disk(5), mode='dilation') >>> temp = spim.binary_dilation(im, structure=disk(5)) >>> array_equal(result, temp) True
>>> result = ps.filters.fftmorphology(im, strel=disk(5), mode='opening') >>> temp = spim.binary_opening(im, structure=disk(5)) >>> array_equal(result, temp) True
>>> result = ps.filters.fftmorphology(im, strel=disk(5), mode='closing') >>> temp = spim.binary_closing(im, structure=disk(5)) >>> array_equal(result, temp) True

porespy.tools.
find_outer_region
(im, r=0)[source]¶ Finds regions of the image that are outside of the solid matrix.
This function uses the rolling ball method to define where the outer region ends and the void space begins.
This function is particularly useful for samples that do not fill the entire rectangular image, such as cylindrical cores or samples with non parallel faces.
Parameters:  im (NDarray) – Image of the porous material with 1’s for void and 0’s for solid
 r (scalar) – The radius of the rolling ball to use. If not specified then a value is calculated as twice maximum of the distance transform. The image size is padded by this amount in all directions, so the image can become quite large and unwieldy if too large a value is given.
Returns: image – A boolean mask the same shape as
im
, containing True in all voxels identified as outside the sample.Return type: NDarray

porespy.tools.
get_border
(shape, thickness=1, mode='edges', return_indices=False)[source]¶ Creates an array of specified size with corners, edges or faces labelled as True. This can be used as mask to manipulate values laying on the perimeter of an image.
Parameters:  shape (array_like) – The shape of the array to return. Can be either 2D or 3D.
 thickness (scalar (default is 1)) – The number of pixels/voxels to place along perimeter.
 mode (string) – The type of border to create. Options are ‘faces’, ‘edges’ (default) and ‘corners’. In 2D ‘faces’ and ‘edges’ give the same result.
 return_indices (boolean) – If
False
(default) an image is returned with the border voxels set toTrue
. IfTrue
, then a tuple with the x, y, z (ifim
is 3D) indices is returned. This tuple can be used directly to index into the image, such asim[tup] = 2
.
Returns: image – An NDarray of specified shape with
True
values at the perimeter andFalse
elsewhereReturn type: NDarray
Notes
TODO: This function uses brute force to create an image then fill the edges using locationbased logic, and if the user requests
return_indices
it finds them usingnp.where
. Since these arrays are cubic it should be possible to use more elegant and efficient indexbased logic to find the indices, then use them to fill an empty image withTrue
using these indices.Examples
>>> import porespy as ps >>> import scipy as sp >>> mask = ps.tools.get_border(shape=[3, 3], mode='corners') >>> print(mask) [[ True False True] [False False False] [ True False True]] >>> mask = ps.tools.get_border(shape=[3, 3], mode='edges') >>> print(mask) [[ True True True] [ True False True] [ True True True]]

porespy.tools.
get_planes
(im, squeeze=True)[source]¶ Extracts three planar images from the volumetric image, one for each principle axis. The planes are taken from the middle of the domain.
Parameters:  im (NDarray) – The volumetric image from which the 3 planar images are to be obtained
 squeeze (boolean, optional) – If True (default) the returned images are 2D (i.e. squeezed). If False, the images are 1 element deep along the axis where the slice was obtained.
Returns: planes – A list of 2Dimages
Return type: list

porespy.tools.
get_slice
(im, center, size, pad=0)[source]¶ Given a
center
location andradius
of a feature, returns the slice object into theim
that bounds the feature but does not extend beyond the image boundaries.Parameters:  im (NDimage) – The image of the porous media
 center (array_like) – The coordinates of the center of the feature of interest
 size (array_like or scalar) – The size of the feature in each direction. If a scalar is supplied, this implies the same size in all directions.
 pad (scalar or array_like) – The amount to pad onto each side of the slice. The default is 0. A
scalar value will increase the slice size equally in all directions,
while an array the same shape as
im.shape
can be passed to pad a specified amount in each direction.
Returns: slices – A list of slice objects, each indexing into one dimension of the image.
Return type: list

porespy.tools.
insert_cylinder
(im, xyz0, xyz1, r)[source]¶ Inserts a cylinder of given radius onto a given image
Parameters:  im (array_like) – Original voxelated image
 xyz1 (xyz0,) – Voxel coordinates of the two end points of the cylinder
 r (int) – Radius of the cylinder
Returns: im – Original voxelated image overlayed with the cylinder
Return type: NDarray
Notes
This function is only implemented for 3D images

porespy.tools.
insert_sphere
(im, c, r)[source]¶ Inserts a sphere of a specified radius into a given image
Parameters:  im (array_like) – Image into which the sphere should be inserted
 c (array_like) – The [x, y, z] coordinate indicating the center of the sphere
 r (int) – The radius of sphere to insert
Returns: image – The original image with a sphere inerted at the specified location
Return type: NDarray

porespy.tools.
in_hull
(points, hull)[source]¶ Test if a list of coordinates are inside a given convex hull
Parameters:  points (array_like (N x ndims)) – The spatial coordinates of the points to check
 hull (scipy.spatial.ConvexHull object OR array_like) – Can be either a convex hull object as returned by
scipy.spatial.ConvexHull
or simply the coordinates of the points that define the convex hull.
Returns: result – A 1Darray Boolean array of length N indicating whether or not the given points in
points
lies within the providedhull
.Return type: 1Darray

porespy.tools.
make_contiguous
(im, keep_zeros=True)[source]¶ Take an image with arbitrary greyscale values and adjust them to ensure all values fall in a contiguous range starting at 0.
This function will handle negative numbers such that most negative number will become 0, unless
keep_zeros
isTrue
in which case it will become 1, and all 0’s in the original image remain 0.Parameters:  im (array_like) – An ND array containing greyscale values
 keep_zeros (Boolean) – If
True
(default) then 0 values remain 0, regardless of how the other numbers are adjusted. This is mostly relevant when the array contains negative numbers, and means that 1 will become +1, while 0 values remain 0.
Returns: image – An NDarray the same size as
im
but with all values in contiguous orders.Return type: NDarray
Example
>>> import porespy as ps >>> import scipy as sp >>> im = sp.array([[0, 2, 9], [6, 8, 3]]) >>> im = ps.tools.make_contiguous(im) >>> print(im) [[0 1 5] [3 4 2]]

porespy.tools.
mesh_region
(region: bool, strel=None)[source]¶ Creates a trimesh of the provided region using the marching cubes algorithm
Parameters:  im (NDarray) – A boolean image with
True
values indicating the region of interest  strel (NDarray) – The structuring element to use when blurring the region. The blur is
perfomed using a simple convolution filter. The point is to create a
greyscale region to allow the marching cubes algorithm some freedom
to conform the mesh to the surface. As the size of
strel
increases the region will become increasingly blurred and inaccurate. The default is a spherical element with a radius of 1.
Returns: mesh – A namedtuple containing
faces
,verts
,norm
, andval
as returned byscikitimage.measure.marching_cubes
function.Return type: tuple
 im (NDarray) – A boolean image with

porespy.tools.
norm_to_uniform
(im, scale=None)[source]¶ Take an image with normally distributed greyscale values and converts it to a uniform (i.e. flat) distribution. It’s also possible to specify the lower and upper limits of the uniform distribution.
Parameters:  im (NDimage) – The image containing the normally distributed scalar field
 scale ([low, high]) – A list or array indicating the lower and upper bounds for the new
randomly distributed data. The default is
None
, which uses themax
andmin
of the original image as the the lower and upper bounds, but another common option might be [0, 1].
Returns: image – A copy of
im
with uniformly distributed greyscale values spanning the specified range, if given.Return type: NDarray

porespy.tools.
overlay
(im1, im2, c)[source]¶ Overlays
im2
ontoim1
, given voxel coords of center ofim2
inim1
.Parameters:  im1 (NDarray) – Original voxelated image
 im2 (NDarray) – Template voxelated image
 c (array_like) – [x, y, z] coordinates in
im1
whereim2
will be centered
Returns: image – A modified version of
im1
, withim2
overlaid at the specified locationReturn type: NDarray

porespy.tools.
randomize_colors
(im, keep_vals=[0])[source]¶ Takes a greyscale image and randomly shuffles the greyscale values, so that all voxels labeled X will be labelled Y, and all voxels labeled Y will be labeled Z, where X, Y, Z and so on are randomly selected from the values in the input image.
This function is useful for improving the visibility of images with neighboring regions that are only incrementally different from each other, such as that returned by scipy.ndimage.label.
Parameters:  im (array_like) – An ND image of greyscale values.
 keep_vals (array_like) – Indicate which voxel values should NOT be altered. The default is [0] which is useful for leaving the background of the image untouched.
Returns: image – An image the same size and type as
im
but with the greyscale values reassigned. The unique values in both the input and output images will be identical.Return type: NDarray
Notes
If the greyscale values in the input image are not contiguous then the neither will they be in the output.
Examples
>>> import porespy as ps >>> import scipy as sp >>> sp.random.seed(0) >>> im = sp.random.randint(low=0, high=5, size=[4, 4]) >>> print(im) [[4 0 3 3] [3 1 3 2] [4 0 0 4] [2 1 0 1]] >>> im_rand = ps.tools.randomize_colors(im) >>> print(im_rand) [[2 0 4 4] [4 1 4 3] [2 0 0 2] [3 1 0 1]]
As can be seen, the 2’s have become 3, 3’s have become 4, and 4’s have become 2. 1’s remained 1 by random accident. 0’s remain zeros by default, but this can be controlled using the keep_vals argument.

porespy.tools.
subdivide
(im, divs=2)[source]¶ Returns slices into an image describing the specified number of subarrays.
This function is useful for performing operations on smaller images for memory or speed. Note that for most typical operations this will NOT work, since the image borders would cause artifacts (e.g.
distance_transform
)Parameters:  im (NDarray) – The image of the porous media
 divs (scalar or array_like) – The number of subdivisions to create in each axis of the image. If a scalar is given it is assumed this value applies in all dimensions.
Returns: slices – A 1D array containing slice objects for indexing into
im
that extract the subdivided arrays.Return type: 1Darray
Notes
This method uses the array_split package which offers the same functionality as the
split
method of Numpy’s NDarray, but supports the splitting multidimensional arrays in all dimensions.Examples
>>> import porespy as ps >>> import matplotlib.pyplot as plt >>> im = ps.generators.blobs(shape=[200, 200]) >>> s = ps.tools.subdivide(im, divs=[2, 2])
s
contains an array with the shape given bydivs
. To access the first and last quadrants ofim
use: >>> print(im[s[0, 0]].shape) (100, 100) >>> print(im[s[1, 1]].shape) (100, 100)It can be easier to index the array with the slices by applying
flatten
first: >>> s_flat = s.flatten() >>> for i in s_flat: … print(im[i].shape) (100, 100) (100, 100) (100, 100) (100, 100)