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
This commit is part of merge request !139. Comments created here will be created in the context of that merge request.
......@@ -33,18 +33,20 @@ class _LazyLoader:
# List of submodules
_submodules = [
"examples",
"generate",
"gui",
"io",
"models",
"processing",
"tests",
"utils",
"viz",
"cli",
'examples',
'generate',
'gui',
'io',
'models',
'processing',
'tests',
'utils',
'viz',
'cli',
'filters',
'segmentation'
]
# Creating lazy loaders for each submodule
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 .structure_tensor_ import structure_tensor
from .detection import blob_detection
from .filters import *
from .operations import *
from .cc import get_3d_cc
from .layers2d import segment_layers, get_lines
......
import numpy as np
import qim3d.processing.filters as filters
import qim3d.filters as filters
from qim3d.utils.logger import log
......@@ -52,74 +52,6 @@ def remove_background(
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(
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
from qim3d.processing.filters import *
from qim3d.filters import *
import numpy as np
import pytest
import re
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment