I was having conversation about data types with Stéfan in the line
comments of a PR, and I thought I should move it here so others can
benefit from his explanations as well.
Being new to the project, I didn't appreciate the intricacies of data
typing. For example, I was surprised to see that this raises a
ValueError:
>>> skimage.img_as_float(np.arange(9).reshape((3, 3)))
The problem is that the default dtype of np.arange is int32, which
isn't supported by skimage, so img_as_float doesn't know how to scale
it to [0, 1]. Perhaps it is correct to fail, as it will force the user
to consider the data type issue. However, it does seem like a
reasonable/common thing to want to do.
A related, but different, issue is the following:
>>> x = np.arange(9, dtype=np.uint8).reshape((3, 3))
>>> x
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]], dtype=uint8)
>>> y = skimage.img_as_ubyte(x.astype(np.float32))
WARNING:dtype_converter:Possible precision loss, converting from
float32 to uint8
>>> y
array([[ 0, 255, 254],
[253, 252, 251],
[250, 249, 248]], dtype=uint8)
The problem here is that the input to img_as_ubyte violates skimage's
assumption that floating point images have the range [0, 1], leading
to an unexpected result (at least for a beginner). There is a warning,
but that's for a different problem. Should img_as_ubyte, img_as_float,
etc. check and enforce ranges? Or raise warnings? Any thoughts?
Neil