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

Add a channel_axis argument to functions in the skimage.color module #5462

Merged
merged 27 commits into from
Aug 9, 2021

Conversation

grlee77
Copy link
Contributor

@grlee77 grlee77 commented Jul 7, 2021

Description

This PR adds a new channel_axis argument to color conversion functions as discussed a bit in #5439 and corresponding recent API-related meetings.

For most functions this is pretty simple, often just requiring adding the channel_axis keyword and the pre-existing channel_as_last_axis decorator. Most of the work was in modifying the test cases to test each function with additional channel axis choices.

One specific case that is a bit tricky is how to handle the adapt_rgb decorator so that it supports channels along any axis instead of always assuming the last axis. I implemented something for that in commit 8063049 that involves inspection of keyword arguments of the decorated function, but I think this is possibly too magical and is perhaps not worth it. It doesn't help that adapt_rgb is also one place where we apparently still try to guess if an image is RGB/RGBA based on its shape. The only function in the library that uses adapt_rgb is skimage.exposure.equalize_adapthist. If we don't want this change I can just revert that commit and/or leave it to a potential future follow-up PR.

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 grlee77 added the ⏩ type: Enhancement Improve existing features label Jul 7, 2021
@pep8speaks
Copy link

pep8speaks commented Jul 7, 2021

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

Line 617:57: E225 missing whitespace around operator

Comment last updated at 2021-08-09 20:26:13 UTC

@grlee77 grlee77 changed the title Color channel axis Add a channel_axis argument to functions in the skimage.color module Jul 7, 2021
@grlee77 grlee77 added the 📜 type: API Involves API change(s) label Jul 8, 2021
@mkcor
Copy link
Member

mkcor commented Jul 17, 2021

One specific case that is a bit tricky is how to handle the adapt_rgb decorator so that it supports channels along any axis instead of always assuming the last axis.

I would be very tempted to drop skimage/color/adapt_rgb.py altogether.

It doesn't help that adapt_rgb is also one place where we apparently still try to guess if an image is RGB/RGBA based on its shape.

Exactly. It's not robust at all and it doesn't generalize to nD. I'm a little scared when I read: "A very simple check of the array shape is used for detecting RGB images, so adapt_rgb is not recommended for functions that support 3D volumes or color images in non-RGB spaces." (note at the bottom of https://scikit-image.org/docs/stable/auto_examples/color_exposure/plot_adapt_rgb.html where we document/encourage the use of the adapt_rgb decorator) 😱

The only function in the library that uses adapt_rgb is skimage.exposure.equalize_adapthist.

I searched all GitHub and found that this project by @lauraluebbert uses skimage.exposure.equalize_adapthist. I'll double check when Binder starts, but it looks like the function is used on single-channel inputs (even though the analyzed dataset consists of colour images).

@grlee77
Copy link
Contributor Author

grlee77 commented Jul 17, 2021

Yeah I think it is best if I just rebase without commit 3d82e2c or 8063049 (I think all adaptrgb-related changes were in those two commits). We can decide about potentially dropping the decorator altogether elsewhere.

@grlee77
Copy link
Contributor Author

grlee77 commented Jul 17, 2021

I decided to use git revert instead of git rebase -i so the commits are still in the history

Copy link
Member

@mkcor mkcor left a comment

Choose a reason for hiding this comment

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

I'm only half-way through, but it's getting late; will finish during the week!

skimage/color/adapt_rgb.py Show resolved Hide resolved
skimage/_shared/utils.py Outdated Show resolved Hide resolved
skimage/color/colorconv.py Outdated Show resolved Hide resolved
skimage/color/colorconv.py Outdated Show resolved Hide resolved
Copy link
Member

@mkcor mkcor left a comment

Choose a reason for hiding this comment

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

I'm confused: I couldn't find channel_as_last_axis defined in skimage/_shared/utils.py--where is it?

channel_axis=channel_axis
),
img_rgb,
)
Copy link
Member

Choose a reason for hiding this comment

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

Nice! 🙂

skimage/color/colorconv.py Outdated Show resolved Hide resolved
skimage/color/colorconv.py Outdated Show resolved Hide resolved
grlee77 and others added 2 commits July 26, 2021 15:44
skimage/color/colorconv.py Outdated Show resolved Hide resolved
@mkcor
Copy link
Member

mkcor commented Jul 27, 2021

I'm confused: I couldn't find channel_as_last_axis defined in skimage/_shared/utils.py--where is it?

False alarm, sorry, I don't know what happened to my sed/grep... 😕

the pre-existing channel_as_last_axis decorator

line 220 of expected file in current main 😅

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 left some suggestions, otherwise it LGTM 😉

skimage/_shared/utils.py Outdated Show resolved Hide resolved
skimage/color/colorconv.py Outdated Show resolved Hide resolved
alpha = np.full(arr.shape, alpha, dtype=arr.dtype)
elif alpha.shape != arr.shape:
raise ValueError("alpha.shape must match image.shape")
rgba = np.stack((arr,) * 3 + (alpha,), axis=channel_axis)
Copy link
Member

Choose a reason for hiding this comment

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

❤️ Very elegant 😉

return rgba


def gray2rgb(image, alpha=None):
def gray2rgb(image, *, channel_axis=-1):
Copy link
Member

Choose a reason for hiding this comment

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

The alpha argument may had be removed in a different PR, but it may be more complicated. Please remove the corresponding item in TODO.txt 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Apparently I did already remove alpha and the TODO item as part of #5463 so perhaps we should merge that first to make this cleaner.

skimage/color/tests/test_colorconv.py Outdated Show resolved Hide resolved
@grlee77
Copy link
Contributor Author

grlee77 commented Aug 5, 2021

Thanks @rfezzani, I implemented the requested changes in the last few commits.

@rfezzani
Copy link
Member

rfezzani commented Aug 6, 2021

@grlee77, if you prefer to merge #5463 prior to this one, there is a conflict in colorlabel.py there 😕

@rfezzani
Copy link
Member

rfezzani commented Aug 9, 2021

@grlee77, we will be ready for merge after conflict resolution 😉

@rfezzani rfezzani merged commit 293fb93 into scikit-image:main Aug 9, 2021
@rfezzani
Copy link
Member

rfezzani commented Aug 9, 2021

🎉 Thank you again @grlee77

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⏩ type: Enhancement Improve existing features 📜 type: API Involves API change(s)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants