Skip to content

Update cuCIM for consistency with scikit-image 0.26#1038

Merged
rapids-bot[bot] merged 28 commits intorapidsai:mainfrom
grlee77:grelee/skimage-0.26-update
Mar 17, 2026
Merged

Update cuCIM for consistency with scikit-image 0.26#1038
rapids-bot[bot] merged 28 commits intorapidsai:mainfrom
grlee77:grelee/skimage-0.26-update

Conversation

@grlee77
Copy link
Copy Markdown
Contributor

@grlee77 grlee77 commented Mar 4, 2026

This PR ports recent API and implementation changes from scikit-image 0.26.

Key Changes

  • There is one new keyword argument, boundary_mode added to binary_blobs.
  • There was some minor refactoring in regionprops and addition of one new property, "intensity_median".
  • There are some new deprecations / removals
    • Previously deprecated shift_x and shift_y arguments to erosion and dilation are now removed
    • For remove_small_objects, the parameter min_size is deprecated in favor of max_size
    • For remove_small_holes, the parameter area_threshold is deprecated in favor of max_size
  • many misc docstring fixes
  • large refactor of geometric transforms code to match the scikit-image 0.26 behavior/API
    • most changes to _shared/utils.py are additional helpers related to this refactor (also ported from scikit-image 0.26)
  • cucim.skimage.segmentation also now has a separate __init__.pyi for lazy loading
  • some existing test cases now load the local copies of test data from the repository instead of relying on fetch (fetch no longer works for these files in scikit-image 0.26).

Possibly follow-up tasks

  • provide batch implementation for intensity_median in _regionprops_gpu.py
  • make decision on deprecating cucim.skimage.morphology.binary_* functions
    • These are deprecated now in scikit-image 0.26.
    • For cuCIM, the binary variants are around 2x faster so I kept them for now. A follow-up task would be to update the grayscale variants to automatically dispatch to the faster binary kernel when possible. Then we could remove the separate binary_* functions without losing performance.

Directory layout change in scikit-image 0.26

  • scikit-image has switched to separate src/skimage and tests/skimage folder layout.
  • I have currently kept the existing folder layout in cuCIM (tests subfolder within each cucim.skimage module)

@grlee77 grlee77 added this to the v26.04.00 milestone Mar 4, 2026
@grlee77 grlee77 requested review from a team as code owners March 4, 2026 14:12
@grlee77 grlee77 added the breaking Introduces a breaking change label Mar 4, 2026
@grlee77 grlee77 requested a review from AyodeAwe March 4, 2026 14:12
@grlee77 grlee77 added the improvement Improves an existing functionality label Mar 4, 2026
@grlee77 grlee77 added this to cucim Mar 4, 2026
grlee77 added 2 commits March 4, 2026 10:03
bump minimum version requirement to scikit-image 0.23 (released april 2024)
@grlee77 grlee77 force-pushed the grelee/skimage-0.26-update branch from f315bed to 2095929 Compare March 4, 2026 19:59
these checks are non-critical and were passing locally but failing on CI
@gforsyth gforsyth removed the request for review from AyodeAwe March 11, 2026 17:00
Copy link
Copy Markdown
Contributor

@gigony gigony left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @grlee77 ,
I found minor issues and typos.
Otherwise, it looks good to me.

grlee77 and others added 2 commits March 16, 2026 20:55
Co-authored-by: Gigon Bae <gigony@gmail.com>
…ve_small_holes and remove_small_objects is used
grlee77 and others added 3 commits March 16, 2026 22:17
Co-authored-by: Gigon Bae <gigony@gmail.com>
…timate.

Also fix existing bug in EssentialMatrixTransform (missing forward of xp kwarg to parent class constructor)
@grlee77
Copy link
Copy Markdown
Contributor Author

grlee77 commented Mar 17, 2026

/merge

@rapids-bot rapids-bot bot merged commit 20fec39 into rapidsai:main Mar 17, 2026
59 checks passed
@github-project-automation github-project-automation bot moved this to Done in cucim Mar 17, 2026
gforsyth pushed a commit to gforsyth/cucim that referenced this pull request Mar 17, 2026
This PR ports recent API and implementation changes from scikit-image 0.26.

### Key Changes
- There is one new keyword argument, `boundary_mode` added to `binary_blobs`.
- There was some minor refactoring in `regionprops` and addition of one new property, "intensity_median".
- There are some new deprecations / removals
  - Previously deprecated `shift_x` and `shift_y` arguments to `erosion` and `dilation` are now removed
  - For `remove_small_objects`, the parameter `min_size` is deprecated in favor of `max_size`
  - For `remove_small_holes`, the parameter `area_threshold` is deprecated in favor of `max_size`
- many misc docstring fixes
- large refactor of geometric transforms code to match the scikit-image 0.26 behavior/API
  - most changes to `_shared/utils.py` are additional helpers related to this refactor (also ported from scikit-image 0.26)
- `cucim.skimage.segmentation` also now has a separate `__init__.pyi` for lazy loading 
- some existing test cases now load the local copies of test data from the repository instead of relying on `fetch` (fetch no longer works for these files in scikit-image 0.26).

### Possibly follow-up tasks
- provide batch implementation for `intensity_median` in `_regionprops_gpu.py`
- make decision on deprecating `cucim.skimage.morphology.binary_*` functions
  - These are deprecated now in scikit-image 0.26.
  - For cuCIM, the binary variants are around 2x faster so I kept them for now. A follow-up task would be to update the grayscale variants to automatically dispatch to the faster binary kernel when possible. Then we could remove the separate `binary_*` functions without losing performance.

### Directory layout change in scikit-image 0.26
- scikit-image has switched to separate `src/skimage` and `tests/skimage` folder layout.
- I have currently kept the existing folder layout in cuCIM (`tests` subfolder within each `cucim.skimage` module)

Authors:
  - Gregory Lee (https://github.com/grlee77)

Approvers:
  - Gil Forsyth (https://github.com/gforsyth)
  - Gigon Bae (https://github.com/gigony)

URL: rapidsai#1038
@gforsyth gforsyth mentioned this pull request Mar 17, 2026
gforsyth pushed a commit to gforsyth/cucim that referenced this pull request Mar 17, 2026
This PR ports recent API and implementation changes from scikit-image 0.26.

### Key Changes
- There is one new keyword argument, `boundary_mode` added to `binary_blobs`.
- There was some minor refactoring in `regionprops` and addition of one new property, "intensity_median".
- There are some new deprecations / removals
  - Previously deprecated `shift_x` and `shift_y` arguments to `erosion` and `dilation` are now removed
  - For `remove_small_objects`, the parameter `min_size` is deprecated in favor of `max_size`
  - For `remove_small_holes`, the parameter `area_threshold` is deprecated in favor of `max_size`
- many misc docstring fixes
- large refactor of geometric transforms code to match the scikit-image 0.26 behavior/API
  - most changes to `_shared/utils.py` are additional helpers related to this refactor (also ported from scikit-image 0.26)
- `cucim.skimage.segmentation` also now has a separate `__init__.pyi` for lazy loading 
- some existing test cases now load the local copies of test data from the repository instead of relying on `fetch` (fetch no longer works for these files in scikit-image 0.26).

### Possibly follow-up tasks
- provide batch implementation for `intensity_median` in `_regionprops_gpu.py`
- make decision on deprecating `cucim.skimage.morphology.binary_*` functions
  - These are deprecated now in scikit-image 0.26.
  - For cuCIM, the binary variants are around 2x faster so I kept them for now. A follow-up task would be to update the grayscale variants to automatically dispatch to the faster binary kernel when possible. Then we could remove the separate `binary_*` functions without losing performance.

### Directory layout change in scikit-image 0.26
- scikit-image has switched to separate `src/skimage` and `tests/skimage` folder layout.
- I have currently kept the existing folder layout in cuCIM (`tests` subfolder within each `cucim.skimage` module)

Authors:
  - Gregory Lee (https://github.com/grlee77)

Approvers:
  - Gil Forsyth (https://github.com/gforsyth)
  - Gigon Bae (https://github.com/gigony)

URL: rapidsai#1038
rapids-bot bot pushed a commit that referenced this pull request Mar 17, 2026
Changes merged into `main` in 20fec39 that are needed for the 26.04 release if we want Python 3.14 support.

Cherry-picked to avoid the 26.06 tag on the `main` branch.

Authors:
  - Gil Forsyth (https://github.com/gforsyth)
  - Gregory Lee (https://github.com/grlee77)

Approvers:
  - Gregory Lee (https://github.com/grlee77)
  - James Lamb (https://github.com/jameslamb)

URL: #1047
Copy link
Copy Markdown
Member

@jakirkham jakirkham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Greg! 🙏

Had looked over this previously and had a few questions. Finished out this review. Please let me know if you have questions on any of this

# SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause

import re
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinks we should keep this spaced out from the license header

Suggested change
import re
import re

Comment on lines 28 to 32
# check CuPy instead of SciPy
CUPY_LT_14 = parse(cp.__version__) < parse("14.0.0a1")


# Starting in SciPy v1.12, 'scipy.sparse.linalg.cg' keyword argument `tol` is
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just out-of-curiosity was this to address a linter issue or something?

Comment on lines -81 to -82
path = fetch("color/tests/ciede2000_test_data.txt")
return np.loadtxt(path, dtype=dtype)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we no longer need to fetch this test data? Is that done somewhere else?

image : array
Input image.
source_range : string
source_range : {'image', 'dtype'}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So is this a dict now?

Comment on lines 698 to +703
Examples
--------
>>> from skimage import data
>>> from skimage as ski
>>> from cucim.skimage import exposure, img_as_float
>>> image = img_as_float(cp.array(data.moon()))
>>> image = img_as_float(cp.array(ski.data.moon()))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was scikit-image's layout changed recently?

Comment on lines -549 to -559
@pytest.mark.parametrize("func", [morphology.erosion, morphology.dilation])
@pytest.mark.parametrize("name", ["shift_x", "shift_y"])
@pytest.mark.parametrize("value", [True, False, None])
def test_deprecated_shift(func, name, value):
img = cp.ones(10)
func(img) # Shouldn't warn

regex = "`shift_x` and `shift_y` are deprecated"
with pytest.warns(FutureWarning, match=regex) as record:
func(img, **{name: value})
assert_stacklevel(record)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guessing the deprecation happened hence we can drop this test

Comment on lines 267 to -280
is_footprint_sequence = _footprint_is_sequence(footprint)
footprint = _shift_footprints(footprint, shift_x, shift_y)

# if isinstance(footprint, tuple) and not is_footprint_sequence:
# if len(footprint) != image.ndim:
# raise ValueError(
# "footprint.ndim={len(footprint)}, image.ndim={image.ndim}"
# )
# if image.ndim == 2 and any(s % 2 == 0 for s in footprint):
# # only odd-shaped footprints are properly handled for tuples
# footprint = cp.ones(footprint, dtype=bool)
# else:
# ndi.grey_erosion(image, size=footprint, output=out)
# return out
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is dropped because it has been unused?

Why did we not need to use it previously?

Comment on lines -166 to -171
def test_3d_similarity_estimation():
# Note: some choices of seed will produce poorly conditioned values,
# leading to NaN in the estimate. We fix the seed here to avoid this.
seed = 10
rng = cp.random.default_rng(seed)
src_points = rng.random(size=(1000, 3))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this test dropped?

Comment on lines -915 to -922
@pytest.mark.parametrize("xp", [np, cp])
def test_similarity_transform_params(xp):
with pytest.raises(ValueError):
_ = SimilarityTransform(
translation=(4, 5, 6, 7), dimensionality=4, xp=xp
)
tf = SimilarityTransform(scale=4, dimensionality=3, xp=xp)
assert_array_equal(tf(xp.asarray([[1, 1, 1]])), xp.asarray([[4, 4, 4]]))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this test dropped?

- pywavelets>=1.6
- recommonmark
- scikit-image>=0.19.0,<0.26.0
- scikit-image>=0.23.2,<0.27.0
Copy link
Copy Markdown
Member

@jakirkham jakirkham Mar 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this was missed in the Conda recipe. We are handling this in PR: #1049

xref: #1049 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Introduces a breaking change improvement Improves an existing functionality

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants