Skip to content
Snippets Groups Projects
Commit 8258ac8b authored by fima's avatar fima :beers:
Browse files

filters and segmentation in place

parent 11da9c42
No related branches found
No related tags found
1 merge request!139Refactoring v1.0 prep
...@@ -33,18 +33,20 @@ class _LazyLoader: ...@@ -33,18 +33,20 @@ class _LazyLoader:
# List of submodules # List of submodules
_submodules = [ _submodules = [
"examples", 'examples',
"generate", 'generate',
"gui", 'gui',
"io", 'io',
"models", 'models',
"processing", 'processing',
"tests", 'tests',
"utils", 'utils',
"viz", 'viz',
"cli", 'cli',
'filters',
'segmentation'
] ]
# Creating lazy loaders for each submodule # Creating lazy loaders for each submodule
for submodule in _submodules: for submodule in _submodules:
globals()[submodule] = _LazyLoader(f"qim3d.{submodule}") globals()[submodule] = _LazyLoader(f'qim3d.{submodule}')
File moved
from .local_thickness_ import local_thickness from .local_thickness_ import local_thickness
from .structure_tensor_ import structure_tensor from .structure_tensor_ import structure_tensor
from .detection import blob_detection from .detection import blob_detection
from .filters import *
from .operations import * from .operations import *
from .cc import get_3d_cc from .cc import get_3d_cc
from .layers2d import segment_layers, get_lines from .layers2d import segment_layers, get_lines
......
import numpy as np import numpy as np
import qim3d.processing.filters as filters import qim3d.filters as filters
from qim3d.utils.logger import log from qim3d.utils.logger import log
...@@ -52,74 +52,6 @@ def remove_background( ...@@ -52,74 +52,6 @@ def remove_background(
return pipeline(vol) return pipeline(vol)
def watershed(bin_vol: np.ndarray, min_distance: int = 5) -> tuple[np.ndarray, int]:
"""
Apply watershed segmentation to a binary volume.
Args:
bin_vol (np.ndarray): Binary volume to segment. The input should be a 3D binary image where non-zero elements
represent the objects to be segmented.
min_distance (int): Minimum number of pixels separating peaks in the distance transform. Peaks that are
too close will be merged, affecting the number of segmented objects. Default is 5.
Returns:
tuple[np.ndarray, int]:
- Labeled volume (np.ndarray): A 3D array of the same shape as the input `bin_vol`, where each segmented object
is assigned a unique integer label.
- num_labels (int): The total number of unique objects found in the labeled volume.
Example:
```python
import qim3d
vol = qim3d.examples.cement_128x128x128
binary = qim3d.processing.filters.gaussian(vol, sigma = 2)<60
qim3d.viz.slices(binary, axis=1)
```
![operations-watershed_before](assets/screenshots/operations-watershed_before.png)
```python
labeled_volume, num_labels = qim3d.processing.operations.watershed(binary)
cmap = qim3d.viz.colormaps.objects(num_labels)
qim3d.viz.slices(labeled_volume, axis = 1, cmap = cmap)
```
![operations-watershed_after](assets/screenshots/operations-watershed_after.png)
"""
import skimage
import scipy
if len(np.unique(bin_vol)) > 2:
raise ValueError("bin_vol has to be binary volume - it must contain max 2 unique values.")
# Compute distance transform of binary volume
distance = scipy.ndimage.distance_transform_edt(bin_vol)
# Find peak coordinates in distance transform
coords = skimage.feature.peak_local_max(
distance, min_distance=min_distance, labels=bin_vol
)
# Create a mask with peak coordinates
mask = np.zeros(distance.shape, dtype=bool)
mask[tuple(coords.T)] = True
# Label peaks
markers, _ = scipy.ndimage.label(mask)
# Apply watershed segmentation
labeled_volume = skimage.segmentation.watershed(
-distance, markers=markers, mask=bin_vol
)
# Extract number of objects found
num_labels = len(np.unique(labeled_volume)) - 1
log.info(f"Total number of objects found: {num_labels}")
return labeled_volume, num_labels
def fade_mask( def fade_mask(
vol: np.ndarray, vol: np.ndarray,
......
from .standard import *
\ No newline at end of file
import numpy as np
from qim3d.utils.logger import log
__all__ = ["watershed"]
def watershed(bin_vol: np.ndarray, min_distance: int = 5) -> tuple[np.ndarray, int]:
"""
Apply watershed segmentation to a binary volume.
Args:
bin_vol (np.ndarray): Binary volume to segment. The input should be a 3D binary image where non-zero elements
represent the objects to be segmented.
min_distance (int): Minimum number of pixels separating peaks in the distance transform. Peaks that are
too close will be merged, affecting the number of segmented objects. Default is 5.
Returns:
tuple[np.ndarray, int]:
- Labeled volume (np.ndarray): A 3D array of the same shape as the input `bin_vol`, where each segmented object
is assigned a unique integer label.
- num_labels (int): The total number of unique objects found in the labeled volume.
Example:
```python
import qim3d
vol = qim3d.examples.cement_128x128x128
binary = qim3d.processing.filters.gaussian(vol, sigma = 2)<60
qim3d.viz.slices(binary, axis=1)
```
![operations-watershed_before](assets/screenshots/operations-watershed_before.png)
```python
labeled_volume, num_labels = qim3d.processing.operations.watershed(binary)
cmap = qim3d.viz.colormaps.objects(num_labels)
qim3d.viz.slices(labeled_volume, axis = 1, cmap = cmap)
```
![operations-watershed_after](assets/screenshots/operations-watershed_after.png)
"""
import skimage
import scipy
if len(np.unique(bin_vol)) > 2:
raise ValueError("bin_vol has to be binary volume - it must contain max 2 unique values.")
# Compute distance transform of binary volume
distance = scipy.ndimage.distance_transform_edt(bin_vol)
# Find peak coordinates in distance transform
coords = skimage.feature.peak_local_max(
distance, min_distance=min_distance, labels=bin_vol
)
# Create a mask with peak coordinates
mask = np.zeros(distance.shape, dtype=bool)
mask[tuple(coords.T)] = True
# Label peaks
markers, _ = scipy.ndimage.label(mask)
# Apply watershed segmentation
labeled_volume = skimage.segmentation.watershed(
-distance, markers=markers, mask=bin_vol
)
# Extract number of objects found
num_labels = len(np.unique(labeled_volume)) - 1
log.info(f"Total number of objects found: {num_labels}")
return labeled_volume, num_labels
\ No newline at end of file
import qim3d import qim3d
from qim3d.processing.filters import * from qim3d.filters import *
import numpy as np import numpy as np
import pytest import pytest
import re import re
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment