Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,14 @@ repos:
^python/cucim/src/cucim/skimage/morphology/_medial_axis_lookup[.]py$|
^python/cucim/src/cucim/skimage/morphology/binary[.]py$|
^python/cucim/src/cucim/skimage/morphology/convex_hull[.]py$|
^python/cucim/src/cucim/skimage/morphology/extrema[.]py$|
^python/cucim/src/cucim/skimage/morphology/footprints[.]py$|
^python/cucim/src/cucim/skimage/morphology/gray[.]py$|
^python/cucim/src/cucim/skimage/morphology/isotropic[.]py$|
^python/cucim/src/cucim/skimage/morphology/misc[.]py$|
^python/cucim/src/cucim/skimage/morphology/tests/test_binary[.]py$|
^python/cucim/src/cucim/skimage/morphology/tests/test_convex_hull[.]py$|
^python/cucim/src/cucim/skimage/morphology/tests/test_extrema[.]py$|
^python/cucim/src/cucim/skimage/morphology/tests/test_footprints[.]py$|
^python/cucim/src/cucim/skimage/morphology/tests/test_gray[.]py$|
^python/cucim/src/cucim/skimage/morphology/tests/test_isotropic[.]py$|
Expand Down Expand Up @@ -483,12 +485,14 @@ repos:
python/cucim/src/cucim/skimage/morphology/_medial_axis_lookup[.]py$|
python/cucim/src/cucim/skimage/morphology/binary[.]py$|
python/cucim/src/cucim/skimage/morphology/convex_hull[.]py$|
python/cucim/src/cucim/skimage/morphology/extrema[.]py$|
python/cucim/src/cucim/skimage/morphology/footprints[.]py$|
python/cucim/src/cucim/skimage/morphology/gray[.]py$|
python/cucim/src/cucim/skimage/morphology/isotropic[.]py$|
python/cucim/src/cucim/skimage/morphology/misc[.]py$|
python/cucim/src/cucim/skimage/morphology/tests/test_binary[.]py$|
python/cucim/src/cucim/skimage/morphology/tests/test_convex_hull[.]py$|
python/cucim/src/cucim/skimage/morphology/tests/test_extrema[.]py$|
python/cucim/src/cucim/skimage/morphology/tests/test_footprints[.]py$|
python/cucim/src/cucim/skimage/morphology/tests/test_gray[.]py$|
python/cucim/src/cucim/skimage/morphology/tests/test_isotropic[.]py$|
Expand Down
58 changes: 53 additions & 5 deletions benchmarks/skimage/cucim_morphology_bench.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@
import skimage.data
import skimage.morphology
from _image_bench import ImageBench
from packaging.version import Version

import cucim.skimage
import cucim.skimage.morphology

# scikit-image >= 0.26 renamed min_size -> max_size in remove_small_objects
# and area_threshold -> max_size in remove_small_holes
_skimage_has_max_size = Version(skimage.__version__) >= Version("0.26")


class BinaryMorphologyBench(ImageBench):
def __init__(
Expand Down Expand Up @@ -107,15 +112,26 @@ def _init_test_data(self, dtype):

def set_args(self, dtype):
a = self._init_test_data(dtype)
self.args_cpu = (cp.asnumpy(a), 6)
self.args_gpu = (a, 6)
self.args_cpu = (cp.asnumpy(a),)
self.args_gpu = (a,)
# scikit-image < 0.26 uses min_size, >= 0.26 uses max_size
if _skimage_has_max_size:
self.fixed_kwargs_cpu["max_size"] = 6
else:
self.fixed_kwargs_cpu["min_size"] = 6
self.fixed_kwargs_gpu["max_size"] = 6


class RemoveSmallHolesBench(RemoveSmallObjectsBench):
def set_args(self, dtype):
a = ~self._init_test_data(dtype)
self.args_cpu = (cp.asnumpy(a), 5)
self.args_gpu = (a, 5)
self.args_cpu = (cp.asnumpy(a),)
self.args_gpu = (a,)
if _skimage_has_max_size:
self.fixed_kwargs_cpu["max_size"] = 5
else:
self.fixed_kwargs_cpu["area_threshold"] = 5
self.fixed_kwargs_gpu["max_size"] = 5


def main(args):
Expand Down Expand Up @@ -161,6 +177,37 @@ def main(args):
("thin", dict(), dict(), False, True),
# grayreconstruct.py
("reconstruction", dict(), dict(), False, True),
# extrema.py
(
"local_maxima",
dict(),
dict(connectivity=list(range(1, len(shape) + 1))),
False,
True,
),
(
"local_minima",
dict(),
dict(connectivity=list(range(1, len(shape) + 1))),
False,
True,
),
# h values scaled to image range: integers use camera (0-255),
# floats use camera/255 (0-1)
(
"h_maxima",
dict(),
dict(h=[10, 40] if np.issubdtype(dtypes[0], np.integer) else [0.04, 0.16]),
False,
True,
),
(
"h_minima",
dict(),
dict(h=[10, 40] if np.issubdtype(dtypes[0], np.integer) else [0.04, 0.16]),
False,
True,
),
# footprints.py
# OMIT the functions from this file (each creates a structuring element)
]:
Expand Down Expand Up @@ -298,7 +345,8 @@ def main(args):
'binary_closing', 'isotropic_erosion', 'isotropic_dilation',
'isotropic_opening', 'isotropic_closing','remove_small_objects',
'remove_small_holes', 'erosion', 'dilation', 'opening', 'closing',
'white_tophat', 'black_tophat', 'thin', 'medial_axis', 'reconstruction'
'white_tophat', 'black_tophat', 'thin', 'medial_axis', 'reconstruction',
'local_maxima', 'local_minima', 'h_maxima', 'h_minima',
]
# fmt: on
dtype_choices = [
Expand Down
4 changes: 2 additions & 2 deletions benchmarks/skimage/run-nv-bench-morphology.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
MAX_DURATION="${CUCIM_BENCHMARK_MAX_DURATION:-10}"

param_shape=("512,512" "3840,2160" "3840,2160,3" "192,192,192")
param_filt=(binary_erosion binary_dilation binary_opening binary_closing isotropic_erosion isotropic_dilation isotropic_opening isotropic_closing remove_small_objects remove_small_holes erosion dilation opening closing white_tophat black_tophat medial_axis thin reconstruction)
param_filt=(binary_erosion binary_dilation binary_opening binary_closing isotropic_erosion isotropic_dilation isotropic_opening isotropic_closing remove_small_objects remove_small_holes erosion dilation opening closing white_tophat black_tophat medial_axis thin reconstruction h_maxima h_minima local_maxima local_minima)
param_dt=(uint8)
for shape in "${param_shape[@]}"; do
for filt in "${param_filt[@]}"; do
Expand All @@ -18,7 +18,7 @@ done

# Note: Omit binary_*, medial_axis and thin from floating point benchmarks.
# (these functions only take binary input).
param_filt_float=(remove_small_objects remove_small_holes erosion dilation opening closing white_tophat black_tophat reconstruction)
param_filt_float=(remove_small_objects remove_small_holes erosion dilation opening closing white_tophat black_tophat reconstruction h_maxima h_minima local_maxima local_minima)
param_dt=(float32)
for shape in "${param_shape[@]}"; do
for filt in "${param_filt_float[@]}"; do
Expand Down
7 changes: 6 additions & 1 deletion python/cucim/src/cucim/skimage/morphology/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# SPDX-FileCopyrightText: 2009-2022 the scikit-image team
# SPDX-FileCopyrightText: Copyright (c) 2021-2025, NVIDIA CORPORATION. All rights reserved.
# SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause

"""Morphological algorithms, e.g., closing, opening, skeletonization."""

from ._skeletonize import medial_axis, thin
from .extrema import h_maxima, h_minima, local_maxima, local_minima
from .binary import (
binary_closing,
binary_dilation,
Expand Down Expand Up @@ -50,6 +51,10 @@
"binary_dilation",
"binary_opening",
"binary_closing",
"h_maxima",
"h_minima",
"local_maxima",
"local_minima",
"isotropic_dilation",
"isotropic_erosion",
"isotropic_opening",
Expand Down
Loading
Loading