Why does multiplying an image, loaded using scikit-image, by 0.5 show it brighter in matplotlib?

105 Views Asked by At

I simply want to darken an image that I've loaded using scikit-image in python.

If I do this:

test_image = io.imread("TestProvs2.bmp")

test_image = test_image * 0.5

show_map(test_image)

The array of RGB values does indeed get scaled down, so that each RGB value is 127.5.

Yet the resulting image has maximum values (left = original, right = new): enter image description here

2

There are 2 best solutions below

2
Ali Ent On BEST ANSWER

When you read an image, the data type of your image is uint8. When you multiply it by 0.5, Python casts it to float64 but an image must be uint8, so it gives this error

Lossy conversion from float64 to uint8. Range [0.0, 127.5]. Convert image to uint8 prior to saving to suppress this warning.

What you have to do is to cast it to uint8 manually.

test_image = (test_image * 0.5).astype(np.uint8)

Don't forget to import numpy

import numpy as np

Generally, it's better to use OpenCV for image processing.

2
Christoph Rackwitz On

The issue is indeed data types, and how matplotlib handles them.

When you have data of type uint8, the value range is expected to be from 0 to 255. An image needs not be uint8. It can have other data types too.

When you have data of type float/float64, the value range is probably expected to be 0.0 .. 1.0. Matplotlib expects this.

If you see a warning like this, that would be an indication of the issue:

Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

Since you merely multiplied your values by 0.5, your value range is 0.0 .. 127.5

Taking that, while expecting a range of upto 1.0, blows out all the pixels.

You fix that either by scaling appropriately, or converting to uint8 explicitly.

matplotlib is perfectly fine to use, for displaying purposes. You just have to check the documentation for what any API will do with your data.