Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify resize implementation using new SciPy 1.6 zoom option #5173

Merged
merged 38 commits into from
Jan 22, 2021

Conversation

grlee77
Copy link
Contributor

@grlee77 grlee77 commented Jan 5, 2021

Description

This PR greatly simplifies the implementation of skimage.transform.resize, by using SciPy 1.6.0's new grid_mode=True option to scipy.ndimage.zoom. This allows us to avoid manually generating coordinates and calling map_coordinates.

numpy.pad -> scipy.ndimage mode conversion was also updated for SciPy 1.6.
closes gh-5064

Currently this new code path replaces both the scipy.ndimage.map_coordinates code path as well as the one relying on scikit-image's own Cython-based interpolation code. We could also potentially leave the existing Cython code path in place (it was ~10-20% faster than ndimage.zoom in 2D with orders 0 or 1). Let me know which is preferred.

It can be seen in the benchmarks below that map_coordinates is occasionally faster than zoom (see e.g. the 3D case for order=5), but this comes at cost of substantially higher memory use needed to store the full set of output coordinates.

ASV benchmarks for resize and rescale (which just calls resize internally) were added. The following table summarizes some results for this PR vs. v0.18.1 in both run time and memory usage. This PR is sometimes substantially faster (3D for order 0, 1) and occasionally a bit slower.

shape order v0.18.1 this PR memory v0.18.1 memory PR
(2000, 4000) 0 62.7 ms 79.6 ms 160 157
(2000, 4000) 1 160 ms 177 ms 160 158
(2000, 4000) 3 531 ms 479 ms 160 166
(2000, 4000) 5 1.48 s 1.04 s 637 166
(150, 150, 150) 0 153 ms 32.8 ms 255 120
(150, 150, 150) 1 230 ms 126 ms 255 120
(150, 150, 150) 3 828 ms 896 ms 255 129
(150, 150, 150) 5 2.44 s 3.04 s 255 129

Checklist

For reviewers

  • Check that the PR title is short, concise, and will make sense 1 year
    later.
  • Check that new functions are imported in corresponding __init__.py.
  • Check that new features, API changes, and deprecations are mentioned in
    doc/release/release_dev.rst.

grlee77 and others added 6 commits January 3, 2021 05:24
- Round trips start with stains, such that the roundtrip does not require
negative values.
- Using a blue+red+orange stain combination, the test previously used
a 2-stain combination that made it impossible to do a correct roundtrip.
use grid-constant and grid-wrap for SciPy >= 1.6.0

closes scikit-imagegh-5064
@grlee77 grlee77 added 🔧 type: Maintenance Refactoring and maintenance of internals 📈 type: Performance labels Jan 5, 2021
@pep8speaks
Copy link

pep8speaks commented Jan 5, 2021

Hello @grlee77! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

Line 189:21: E226 missing whitespace around arithmetic operator
Line 252:13: E126 continuation line over-indented for hanging indent
Line 255:13: E123 closing bracket does not match indentation of opening bracket's line

Line 31:31: E226 missing whitespace around arithmetic operator

Line 150:60: W504 line break after binary operator

Comment last updated at 2021-01-22 02:51:54 UTC

@emmanuelle
Copy link
Member

transform/tests/test_warps.py::test_downsize_anti_aliasing seems to be failing consistently.

@emmanuelle
Copy link
Member

Maybe an item should be added in the TODO so that we don't forget to remove the other code when the scipy dep is bumped to 1.6 (this will probably take some time... so a reminder might be good).

@grlee77
Copy link
Contributor Author

grlee77 commented Jan 5, 2021

transform/tests/test_warps.py::test_downsize_anti_aliasing seems to be failing consistently.

I was relying on SciPy to raise on unrecognized modes, but SciPy raises a RuntimeError rather than the ValueError the test was expecting. I added a ValueError again here for consistency with prior behavior, but if you don't think it is important we can just remove that error check from the tests.

Comment on lines +110 to +111
* When ``scipy`` is set to >= 1.16, remove legacy (i.e. non-zoom) code paths in
``skimage.transform.resize``.
Copy link
Member

Choose a reason for hiding this comment

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

Thanks to NEP-29, we can now do date-based reminders (🎉!): this will be done on Jan 1 2022. Should we add a separate time-based section to the todos?

Copy link
Member

Choose a reason for hiding this comment

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

good idea, yes

Copy link
Member

Choose a reason for hiding this comment

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

Oops — that should be 2023. Time flies when you're having fun! =P

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See how this latest commit reorganizing the "Other" section looks.

We can actually do many of the 2021 items now (we already require NumPy 1.16 and we SciPy 1.1 was released in May 2018).

@jni
Copy link
Member

jni commented Jan 6, 2021

Love it! I think the few specific cases where performance is worse, the tradeoff is worth it for code simplicity.

Alexandre de Siqueira and others added 4 commits January 5, 2021 22:18
…cikit-image#5175)

This should avoid stochastic test failures that have been occuring on GitHub Actions
* Add normalized mutual information metric

* Add tests for NMI

* Add NMI to metrics init

* Fix error message for incorrect target shape

* Add 3D NMI test

* properly add nmi to metrics init

* _true, _test -> 0, 1

* ravel -> reshape(-1)

* Apply suggestions from @mkcor's code review

Co-authored-by: Marianne Corvellec <marianne.corvellec@ens-lyon.org>

* Fix warning and exception messages

Co-authored-by: Marianne Corvellec <marianne.corvellec@ens-lyon.org>
based on NEP-29 24 month window for dropping upstream package version
mode 'nearest' is a scipy.ndimage mode, but warp only accepts the numpy.pad equivalent of 'edge'
Right now the data is not sampled every half degree. Also, -pi/2 to pi/2.
…5182)

* Correction to linspace call in hough_line default

`theta = np.pi / 2 - np.arange(180) / 180.0 * np.pi` done correctly below.

* BUG: Fixup to image orientation in example

* DOC: Tiny typo

* Changed range to conform to documentation

The original was [pi/2, -pi/2), not [-pi/2, pi/2). Updated wording in docs.

* Fixed x-bounds of hough image in example

* Fixed long line

* Fixes to tests

Number of lines in checkerboard, longer line in peak ordering assertion, updated angle

* Accidentally modified the wrong value.

* Updated example to include three lines

As requested in review
madphysicist and others added 4 commits January 15, 2021 08:04
* Replace correlate_sparse Cython version with a simple slicing-based variant in _mean_std

This slicing variant has two benefits:
1.) profiled 30-40% faster on 2d and 3d cases I tested with
2.) can immediately be used by other array backends such as CuPy

* remove intermediate padded_sq variable to reduce memory footprint

* Update skimage/filters/_sparse.py

remove duplicate declarations

Co-authored-by: Riadh Fezzani <rfezzani@gmail.com>

* move _to_np_mode and _to_ndimage_mode to _shared.utils.py

* add comment about corner_index needing to be present

* raise RuntimeError on missing corner index

* update code style based on reviewer comments

Co-authored-by: Riadh Fezzani <rfezzani@gmail.com>
…ikit-image#5187)

Co-authored-by: Juan Nunez-Iglesias <juan.nunez-iglesias@monash.edu>
Copy link
Member

@rfezzani rfezzani left a comment

Choose a reason for hiding this comment

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

Thank you @grlee77, I added some suggestions/remarks, but the PR is good as is 😉

@@ -76,7 +76,7 @@ def _tvl1(reference_image, moving_image, flow0, attachment, tightness,
[1] + reference_image.ndim * [3])

image1_warp = warp(moving_image, get_warp_points(grid, flow_current),
mode='nearest')
Copy link
Member

Choose a reason for hiding this comment

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

👀 Was this a bug?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it was an unintentional use of the scipy.ndimage name rather than letting the function convert from the numpy.pad equivalent name ('edge'). The docstring to warp conforms to numpy.pad style names (i.e. 'edge' rather than its scipy.ndimage equivalent: 'nearest'). It just so happened that warp didn't raise an error on unrecognized modes and just passed them along unmodified.

Copy link
Member

Choose a reason for hiding this comment

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

May be something to investigate 😕...

skimage/transform/_warps.py Outdated Show resolved Hide resolved
@@ -6,15 +6,6 @@
from .._shared.utils import get_bound_method_class, safe_as_int


def _to_ndimage_mode(mode):
Copy link
Member

Choose a reason for hiding this comment

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

I see in master branch that _to_ndimage_mode is not used in this file but we are reimporting it from skimage._shared.utils 😖

Copy link
Contributor Author

Choose a reason for hiding this comment

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

is this just a comment or are you recommending something here? (I didn't quite follow where we are "reimporting it from")

Copy link
Member

Choose a reason for hiding this comment

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

It was just a comment 🙂

skimage/_shared/utils.py Outdated Show resolved Hide resolved
mark-boer and others added 2 commits January 20, 2021 18:35
* Change dtype of CircleModel and EllipseModel to float, to avoid integer overflows

* remove failing test and add code review notes

* Apply suggestions from code review

Co-authored-by: Stefan van der Walt <sjvdwalt@gmail.com>

* Remove unused pytest import

Co-authored-by: Stefan van der Walt <sjvdwalt@gmail.com>

Co-authored-by: Stefan van der Walt <sjvdwalt@gmail.com>
Co-authored-by: Juan Nunez-Iglesias <juan.nunez-iglesias@monash.edu>
@rfezzani
Copy link
Member

@grlee77, it looks like a rebase is necessary :)

grlee77 added a commit to grlee77/scikit-image that referenced this pull request Jan 22, 2021
reuse implementation from scikit-imagegh-5173
@rfezzani rfezzani merged commit d2fb610 into scikit-image:master Jan 22, 2021
@grlee77 grlee77 deleted the resize_using_zoom branch July 8, 2021 20:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📈 type: Performance 🔧 type: Maintenance Refactoring and maintenance of internals
Projects
None yet
Development

Successfully merging this pull request may close these issues.

enable scipy grid-constant boundary handling
10 participants