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

Ep3: iio.imread is unreliable #249

Closed
gcapes opened this issue Feb 8, 2023 · 8 comments · Fixed by #253
Closed

Ep3: iio.imread is unreliable #249

gcapes opened this issue Feb 8, 2023 · 8 comments · Fixed by #253
Assignees
Labels
status:in progress Contributor working on issue type:enhancement Propose enhancement to the lesson

Comments

@gcapes
Copy link

gcapes commented Feb 8, 2023

I wasn't able to load the sudoku image properly using iio.imread but it worked ok using matplotlib.
I wonder if anyone else has had any trouble? Images up to this point in the lesson have loaded ok.

image

image

@mkcor
Copy link
Contributor

mkcor commented Feb 8, 2023

Hi @gcapes,

There is a sentence related to this in episode 5 and I realize it should be moved to episode 3 instead, when using mode="L" first appears. Sorry!

"The first argument to iio.imread() is the filename of the image. The second argument mode="L" defines the type and depth of a pixel in the image (e.g., an 8-bit pixel has a range of 0-255). This argument is forwarded to the pillow backend, for which mode “L” means 8-bit pixels and single-channel (i.e., grayscale). pillow is a Python imaging library; which backend is used by iio.imread() may be specified (to use pillow, you would pass this argument: plugin="pillow"); if unspecified, iio.imread() determines the backend to use based on the image type."

Do you have pillow installed?

@gcapes
Copy link
Author

gcapes commented Feb 9, 2023

Thanks for the quick reply !

I have now installed pillow into my venv but that doesn't look to be the issue. mode="L" doesn't look to be the problem either. If I remove that argument, I get a completely white image instead of completely black.

image

@mkcor
Copy link
Contributor

mkcor commented Feb 9, 2023

Which OS are you running? Were you able to follow https://datacarpentry.org/image-processing/setup/? I guess the test at the end will give you a blank image at this point...

@gcapes
Copy link
Author

gcapes commented Feb 9, 2023

I'm on Linux Mint. I'm not using Anaconda, but have set up a venv with all the required packages as far as I can tell, including scikit-image version 0.19.3 using python 3.10.

The test gives me what looks to be success:

image

I've worked round this problem it for the tutorial, so I'm only really reporting it as something which might affect other learners. It only seems to affect that png image. JPG and TIFF are loading ok.

Feel free to close if this isn't reproducible. Thanks!

@mkcor
Copy link
Contributor

mkcor commented Feb 9, 2023

Strange... I cannot reproduce it on my end, indeed (the PNG image is displaying fine for me); I'm running Python 3.9.15 on Debian GNU/Linux 11 (bullseye).

@tobyhodges
Copy link
Member

tobyhodges commented Feb 9, 2023

I can reproduce this.

Reproducing the error observed by Gerard

(Aside: there is also a small error in the solution block, where we have forgotten to import imageio as iio.)

The immediate issue is coming from the way that mode='L' will return 8-bit integer values (rather than floating point intensities between 0 and 1 as produced by skimage.color.rgb2gray):

Examining the data type of the loaded image array

The rest of the solution assumes that the image array contains values between 0 and 1 but really they are between 0 and 255.

@gcapes here is a solution that should work for the exercise:

import imageio.v3 as iio
import matplotlib.pyplot as plt

image = iio.imread(uri="data/sudoku.png", mode="L")
image[image > 190] = 190
plt.imshow(image, cmap='gray', vmin=0, vmax=255)

Moving onto the question of how to fix this, it is made quite complicated by the fact that the sudoku image has an alpha channel. So skimage.color.rgb2gray returns an error:

import skimage.color
image = iio.imread(uri="data/sudoku.png")
gray_image = skimage.color.rgb2gray(image)
ValueError: the input array must have size 3 along `channel_axis`, got (900, 900, 4)

I can propose four options from here:

  1. We find a way to load the image as floating point intensity values
  2. We adjust the rest of the exercise to work with 8-bit integer values, and highlight the difference between the outputs of skimage.color.rgb2gray and iio.imread(mode='L') in the Converting colour images to grayscale section above the exercise.
  3. We adopt the skimage.color.rgb2gray approach to solve this exercise, and talk through the existence of the alpha channel and how to deal with it.
  4. We remove the alpha channel from the image, and provide a three-channel version as the example file in the data folder, then use the rgb2gray approach.

Here are my thoughts on each of these:

  1. I do not know if this is possible. A quick review of the Pillow documentation did not seem to show me a mode we could use to achieve it.
  2. We should add the note about the different outputs to the Converting colour images to grayscale section.
  3. I would really prefer to avoid a discussion of alpha channels at this stage of the lesson, and the middle of an exercise is definitely not the right place for it regardless.
  4. This would be easy enough to do, even if it does mean creating a new version of the dataset on FigShare. But I wonder if really we want to be recommending mode='L' over rgb2gray in general.

Thoughts very welcome from anyone with more working experience of image processing @mkcor @bobturneruk @K-Meech @quist00 @uschille

@gcapes
Copy link
Author

gcapes commented Feb 9, 2023

Well done @tobyhodges for getting to the bottom of this!
I would suggest option 4. It requires the least extra explaining and keeps to the learning objectives.

@mkcor
Copy link
Contributor

mkcor commented Feb 9, 2023

Oh, sorry, I had skipped the vmin=0, vmax=1 arguments in the plotting function... Mystery solved.

I agree that using a conversion function such as rgb2gray is a more robust practice and it is more transparent to the learner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status:in progress Contributor working on issue type:enhancement Propose enhancement to the lesson
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants