Skip to content

Commit

Permalink
Merge pull request #66 from fmi-faim/filter
Browse files Browse the repository at this point in the history
filter: add dilate and feature filter
  • Loading branch information
imagejan authored Apr 15, 2024
2 parents 568e036 + 39d01e7 commit 45d012d
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 10 deletions.
32 changes: 23 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,29 @@ Configuration is managed in a `config.yml` file:

```yaml
# Required
file_selection: # criteria for file selection in case of multiple channels/slices per position

# criteria for file selection in case of multiple channels/slices per position
file_selection:
channel: C01
process: # choose method how to segment, filter, and sample the objects
segment: threshold # choices: threshold, cellpose
filter: [bounding_box, area, solidity, intensity]
sample: centers # choices: centers, grid_overlap, dense_grid, object_centered_grid, region_centered_grid

# Each subsequent section provides arguments to one of the methods defined in 'process'.
# choose method how to segment, filter, and sample the objects
process:
# segment methods: threshold, cellpose
segment: threshold
# filter methods: bounding_box, area, solidity, intensity
filter: [bounding_box, area, solidity, feature, dilate, intensity]
# sample methods: centers, grid_overlap, dense_grid,
# object_centered_grid, region_centered_grid
sample: centers

# Each section below provides arguments to one of the methods set in 'process'.
# Config sections for methods not selected above will be ignored.

# segment
threshold:
threshold: 128
include_holes: yes
gaussian_sigma: 2.0 # default: 0.0
include_holes: true
gaussian_sigma: 0.0 # default: 0.0

# filter
bounding_box:
Expand All @@ -61,13 +69,19 @@ area:
solidity:
min_solidity: 0.9
max_solidity: 1.0
feature:
feature: eccentricity
min_value: 0.0
max_value: 0.99
dilate:
pixel_distance: 1.0
intensity:
target_channel: C03
min_intensity: 128

# sample
dense_grid:
binning_factor: 20 # default: 50
binning_factor: 50 # default: 50
grid_overlap:
mag_first_pass: 4
mag_second_pass: 60
Expand Down
8 changes: 7 additions & 1 deletion config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ process:
# segment methods: threshold, cellpose
segment: threshold
# filter methods: bounding_box, area, solidity, intensity
filter: [bounding_box, area, solidity, intensity]
filter: [bounding_box, area, solidity, feature, intensity, dilate]
# sample methods: centers, grid_overlap, dense_grid,
# object_centered_grid, region_centered_grid
sample: centers
Expand All @@ -40,6 +40,12 @@ area:
solidity:
min_solidity: 0.9
max_solidity: 1.0
feature:
feature: eccentricity
min_value: 0.0
max_value: 0.99
dilate:
pixel_distance: 1.0
intensity:
target_channel: C03
min_intensity: 128
Expand Down
27 changes: 27 additions & 0 deletions src/faim_wako_searchfirst/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from numpy import ndarray
from skimage.measure import regionprops
from skimage.segmentation import expand_labels
from tifffile import imread


Expand All @@ -40,6 +41,23 @@ def area(
labels[labels == region.label] = 0


def feature(
tif_file: Path,
labels: ndarray,
feature: str,
min_value: float,
max_value: float,
):
"""Filter objects in 'labels' by specified feature value range."""
regions = regionprops(labels)
if hasattr(regions[0], feature):
for region in regions:
if not min_value <= getattr(region, feature) <= max_value:
labels[labels == region.label] = 0
else:
raise AttributeError(f"'regionprops' object has no attribute '{feature}'")


def solidity(
tif_file: Path,
labels: ndarray,
Expand All @@ -53,6 +71,15 @@ def solidity(
labels[labels == region.label] = 0


def dilate(
tif_file: Path,
labels: ndarray,
pixel_distance: float = 10.0,
):
"""Dilate objects by specified amount."""
labels[:] = expand_labels(label_image=labels, distance=pixel_distance)


def intensity(
tif_file: Path,
labels: ndarray,
Expand Down
42 changes: 42 additions & 0 deletions tests/test_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# SPDX-FileCopyrightText: 2024 Friedrich Miescher Institute for Biomedical Research (FMI), Basel (Switzerland)
#
# SPDX-License-Identifier: MIT

"""Test faim_wako_searchfirst.filter module."""

from pathlib import Path

import numpy as np
import pytest
from faim_wako_searchfirst.filter import dilate, feature
from skimage.io import imread


@pytest.fixture
def _label_image():
return imread(Path("tests") / "resources" / "simple_labels.tif")


def test_feature(_label_image: np.ndarray):
"""Test generic feature filter."""
labels = _label_image.copy()
feature(
tif_file=None,
labels=labels,
feature="solidity",
min_value=0.9,
max_value=1.0,
)
assert np.unique(labels).tolist() == [0, 2, 3, 4]


def test_dilate(_label_image: np.ndarray):
"""Test oject dilation."""
labels = _label_image.copy()
assert np.sum(labels[labels == 1]) == 1353
dilate(
tif_file=None,
labels=labels,
pixel_distance=5.0,
)
assert np.sum(labels[labels == 1]) == 2803

0 comments on commit 45d012d

Please sign in to comment.