Processing data
Here, we provide functionalities designed specifically for 3D image analysis and processing. From filter pipelines to structure tensor computation and blob detection, qim3d equips you with the tools you need to extract meaningful insights from your data.
qim3d.processing.structure_tensor
structure_tensor(
volume,
sigma=1.0,
rho=6.0,
base_noise=True,
smallest=True,
visualize=False,
**viz_kwargs,
)
Computes the Structure Tensor for 3D local orientation analysis.
The structure tensor is a matrix-based representation of partial derivatives. It is used to analyze the local orientation of features (like fibers, veins, or layers) in a 3D volume. By examining the eigenvalues and eigenvectors of this tensor, one can determine the dominant direction of structures at every voxel.
This implementation wraps the structure-tensor package, which offers fast, GPU-accelerated computation suitable for large datasets (e.g., micro-CT).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
volume
|
ndarray
|
The input 3D volume. |
required |
sigma
|
float
|
The noise scale. This defines the standard deviation of the Gaussian kernel used to smooth the image before calculating gradients. Features smaller than this scale are suppressed. Defaults to 1.0. |
1.0
|
rho
|
float
|
The integration scale. This defines the size of the neighborhood over which orientation information is averaged (integrated). Larger values yield smoother orientation fields but may blur distinct features. Defaults to 6.0. |
6.0
|
base_noise
|
bool
|
If |
True
|
smallest
|
bool
|
If |
True
|
visualize
|
bool
|
If |
False
|
**viz_kwargs
|
Any
|
Additional keyword arguments passed to the visualization function (e.g., |
{}
|
Returns:
| Type | Description |
|---|---|
(val, vec)
|
A tuple containing:
* val (np.ndarray): An array of shape |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the input |
Example
import qim3d
vol = qim3d.examples.fibers_150x150x150
val, vec = qim3d.processing.structure_tensor(vol, visualize = True, axis = 1)
Runtime and memory usage
Performance computed on Intel(R) Xeon(R) Gold 6226 CPU @ 2.70GHz.
Reference
Jeppesen, N., et al. "Quantifying effects of manufacturing methods on fiber orientation in unidirectional composites using structure tensor analysis." Composites Part A: Applied Science and Manufacturing 149 (2021): 106541. https://doi.org/10.1016/j.compositesa.2021.106541
@article{JEPPESEN2021106541,
title = {Quantifying effects of manufacturing methods on fiber orientation in unidirectional composites using structure tensor analysis},
journal = {Composites Part A: Applied Science and Manufacturing},
volume = {149},
pages = {106541},
year = {2021},
issn = {1359-835X},
doi = {[https://doi.org/10.1016/j.compositesa.2021.106541](https://doi.org/10.1016/j.compositesa.2021.106541)},
url = {[https://www.sciencedirect.com/science/article/pii/S1359835X21002633](https://www.sciencedirect.com/science/article/pii/S1359835X21002633)},
author = {N. Jeppesen and L.P. Mikkelsen and A.B. Dahl and A.N. Christensen and V.A. Dahl}
}
Source code in qim3d/processing/_structure_tensor.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | |
qim3d.processing.local_thickness
Computes the local thickness map for a 2D or 3D image.
Local Thickness is a morphometric measure defined as the diameter of the largest sphere that fits entirely within the object boundary and contains the point. Intuitively, it represents the "width" of the structure at any given voxel. It is widely used to analyze pore sizes, trabecular bone thickness, or vessel diameters.
This function wraps the localthickness package, which implements the "Fast Local Thickness" algorithm. Unlike traditional methods that use computationally expensive large structuring elements, this algorithm uses iterative dilation with small kernels, making it significantly faster and feasible for high-resolution 3D microscopy data.
Note: This function requires a binary image. If a grayscale image is provided, it will be automatically binarized using Otsu's thresholding method.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
ndarray
|
The input 2D or 3D array. * Binary: Processed directly. * Grayscale: Automatically binarized using Otsu's method (a warning will be logged). |
required |
scale
|
float
|
A downscaling factor to speed up computation. For example, |
1
|
mask
|
ndarray
|
A binary mask of the same shape as |
None
|
visualize
|
bool
|
If |
False
|
**viz_kwargs
|
Any
|
Additional keyword arguments passed to the visualization function. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
local_thickness |
ndarray
|
A NumPy array of the same shape as the input, where each pixel/voxel value represents the local thickness at that point. |
Example
import qim3d
vol = qim3d.examples.fly_150x256x256
lt_vol = qim3d.processing.local_thickness(vol, visualize=True, axis=0)
import qim3d
# Generate synthetic collection of blobs
vol, labels = qim3d.generate.volume_collection(num_volumes=15)
# Extract one slice to show that local thickness works on 2D slices too
slice = vol[:,:,50]
lt_blobs = qim3d.processing.local_thickness(slice, visualize=True)
Runtime and memory usage
Performance computed on Intel(R) Xeon(R) Gold 6226 CPU @ 2.70GHz.
Reference
Dahl, V. A., & Dahl, A. B. (2023, June). Fast Local Thickness. 2023 IEEE/CVF Conference on Computer Vision and Pattern Recognition Workshops (CVPRW). https://doi.org/10.1109/cvprw59228.2023.00456
@inproceedings{Dahl_2023, title={Fast Local Thickness},
url={[http://dx.doi.org/10.1109/CVPRW59228.2023.00456](http://dx.doi.org/10.1109/CVPRW59228.2023.00456)},
DOI={10.1109/cvprw59228.2023.00456},
booktitle={2023 IEEE/CVF Conference on Computer Vision and Pattern Recognition Workshops (CVPRW)},
publisher={IEEE},
author={Dahl, Vedrana Andersen and Dahl, Anders Bjorholm},
year={2023},
month=jun }
Source code in qim3d/processing/_local_thickness.py
qim3d.processing.get_lines
Extracts 1D line coordinates from 2D binary segmentation masks.
This utility function is designed to work with the output of qim3d.processing.segment_layers. It converts the binary masks (which split the image into "above" and "below" a layer) into a 1D array of height indices. This allows for easy plotting of the layer boundary using Matplotlib.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
segmentations
|
list[ndarray]
|
A list of 2D binary arrays, typically returned by |
required |
Returns:
| Name | Type | Description |
|---|---|---|
segmentation_lines |
list[ndarray]
|
A list of 1D arrays. Each array contains the vertical index (y-coordinate) of the layer boundary for every horizontal position (x-coordinate). |
Example
Source code in qim3d/processing/_layers.py
qim3d.processing.segment_layers
segment_layers(
data,
inverted=False,
n_layers=1,
delta=1,
min_margin=10,
max_margin=None,
wrap=False,
)
Segments distinct layers in 2D or 3D data using graph-based optimal surface detection.
This function identifies continuous surfaces (layers) within the volume that minimize a specific cost function. It uses a Graph Cut (Max-Flow/Min-Cut) algorithm to find the global optimum. This is particularly useful for detecting boundaries in geological strata, biological tissues (e.g., retinal layers), or material interfaces.
It acts as a wrapper around the slgbuilder library.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
ndarray
|
The 2D or 3D input array. The algorithm assumes layers are stacked along the first dimension (axis 0). |
required |
inverted
|
bool
|
If |
False
|
n_layers
|
int
|
The number of surfaces/boundaries to detect. Defaults to 1. |
1
|
delta
|
float
|
The smoothness penalty. Higher values enforce smoother (stiffer) layer boundaries, resisting sudden changes in height. Defaults to 1. |
1
|
min_margin
|
int or None
|
The minimum vertical distance (in pixels/voxels) allowed between consecutive layers. Used to prevent surfaces from crossing or collapsing onto each other. Defaults to 10. |
10
|
max_margin
|
int or None
|
The maximum vertical distance allowed between consecutive layers. Defaults to |
None
|
wrap
|
bool
|
If |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
segmentations |
list[ndarray]
|
A list of binary masks (0s and 1s), where each mask represents the region defined by a detected layer. The list length equals |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If |
Example
import qim3d
import matplotlib.pyplot as plt
# Load data (using a 2D slice for this example)
# In this image, we want to find 2 distinct boundaries
layers_image = qim3d.io.load('layers3d.tif')[:,:,0]
# Segment the layers
layers = qim3d.processing.segment_layers(layers_image, n_layers=2)
# Extract the line coordinates for plotting
layer_lines = qim3d.processing.get_lines(layers)
# Visualize
plt.imshow(layers_image, cmap='gray')
plt.axis('off')
for layer_line in layer_lines:
plt.plot(layer_line, linewidth=3, label='Detected Layer')
plt.legend()
plt.show()
Source code in qim3d/processing/_layers.py
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | |