Scipy: Wrong image scaling in scipy/misc/pilutil.py with misc.imsave?

Created on 2 Oct 2015  路  4Comments  路  Source: scipy/scipy

I just wanted to check how images with color values out of range are scaled and don't get the logic(function bytescale):
By default low=0 and high=256
if cmin is None:
cmin = data.min() # darkest pixel
if cmax is None:
cmax = data.max()

cscale = cmax - cmin
if cscale < 0:
    raise ValueError("`cmax` should be larger than `cmin`.")
elif cscale == 0:
    cscale = 1

scale = float(high - low) / cscale
bytedata = (data * 1.0 - cmin) * scale + 0.4999 # Important line
bytedata[bytedata > high] = high
bytedata[bytedata < 0] = 0
return cast[uint8](bytedata) + cast[uint8](low)

What happens here, is that the darkest pixel in the image will become the new black. For example, if the darkest pixel has value 10, the image is subtracted by 10 without any reason.
At the same time the maximum value will be 255 as scale is computed.
I see that, there are different modes to decide wether to scale like this or in another way in toimage but for example misc.imsave is using the default mode which is doing this kind of scaling and as such saving images in a non-normal way.

So in my opinion either the default-behaviour of bytescale/toimage should be modified or toimage should provide a parameter so misc.imsave could change the way how the image is scaled.
Any comment is appreciated

defect scipy.misc

Most helpful comment

I have to say.... thank you to everyone who made Scipy, but for the author of scipy.misc.imsave: No one, no one should write a function which silently changes ("dynamically rescales") the data which the user passes to the function for it to simply write it to disk. imsave should _save_ the data to disk, and that's it. Don't change my data without telling me, and for God's sake at least document this "feature" somewhere. This cost me a couple of months of head scratching to figure out why my neural network model was completely off, and it was simply because scipy.misc.imsave does not do what the job description says. Just save the image and don't mess with my data.

If I had wanted to rescale the pixel values then I would have done that myself, e.g. by calling a function called scipy.misc.rescalecolors() or some such, not imsave. At the _very_ least it should be defined as

def imsave(image, path, do_rescale=False):
#etc

For other users who need an alternative, scikit-image has a function called skimage.io.imsave which does not exhibit this behaviour.

All 4 comments

I suppose there are many cases where the current behavior of imsave is reasonable, but I also agree that it should be possible to override this scaling. Suggestions for a revised (but backwards-compatible) imsave API are welcome.

P.S. I recently put some code on github for saving an array (or a sequence of arrays) to a PNG file: https://github.com/WarrenWeckesser/numpngw
The current version of numpngw.write_png doesn't scale the input data (but when a bit depth less than 8 is requested, the high bits of the input data are simply ignored).

I'm working on something

I have to say.... thank you to everyone who made Scipy, but for the author of scipy.misc.imsave: No one, no one should write a function which silently changes ("dynamically rescales") the data which the user passes to the function for it to simply write it to disk. imsave should _save_ the data to disk, and that's it. Don't change my data without telling me, and for God's sake at least document this "feature" somewhere. This cost me a couple of months of head scratching to figure out why my neural network model was completely off, and it was simply because scipy.misc.imsave does not do what the job description says. Just save the image and don't mess with my data.

If I had wanted to rescale the pixel values then I would have done that myself, e.g. by calling a function called scipy.misc.rescalecolors() or some such, not imsave. At the _very_ least it should be defined as

def imsave(image, path, do_rescale=False):
#etc

For other users who need an alternative, scikit-image has a function called skimage.io.imsave which does not exhibit this behaviour.

Was this page helpful?
0 / 5 - 0 ratings