Bizzare matplotlib behaviour in displaying images cast as floats
<p>When a regular RGB image in range (0,255) is cast as float, then displayed by matplotlib, the image is displayed as negative. If it is cast as uint8, it displays correctly (of course). It caused me some trouble to figure out what was going on, because I accidentally cast one of images as float. </p>

<p>I am well aware that when cast as float, the image is expected to be in range (0,1), and sure enough, when divided by 255 the image displayed is correct. But, why would an image in range (0,255) that is cast as float displayed as negative? I would have expected either saturation (all white) or automatically inferred the range from the input (and thus correctly displayed)? If either of those expected things happened, I would have been able to debug my code quicker. I have included the required code to reproduce the behaviour. Does anyone have insight on why this happens?</p>

<pre><code>    import numpy as np
    import matplotlib.pyplot as plt
    a = np.random.randint(0,127,(200,400,3))
    b = np.random.randint(128,255,(200,400,3))
    img=np.concatenate((a,b)) # Top should be dark ; Bottom should be light
    plt.imshow(img) # Inverted
    plt.figure()
    plt.imshow(np.float64(img)) # Still Bad. Added to address sascha's comment
    plt.figure()
    plt.imshow(255-img) # Displayed Correctly
    plt.figure()
    plt.imshow(np.uint8(img)) # Displayed Correctly
    plt.figure()
    plt.imshow(img/255.0) # Displays correctly
</code></pre>

<p>I think you are on a wrong path here as you are claiming, that <code>np.random.randint()</code> should return an float-based array. <strong>It does not!</strong> (<a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.random.randint.html" rel="nofollow">docs</a>)</p>

<p><strong>This means</strong>:</p>

<p>Your first plot is calling imshow with an <strong>numpy-array of dtype=int64</strong>. This is not allowed as seen <a href="http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.imshow" rel="nofollow">here</a>!</p>

<p>The only allowed dtypes for your dimensions are described as: (<a href="http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.imshow" rel="nofollow">see docs</a>):</p>

<pre><code>MxNx3 â RGB (float or uint8 array)  # there are others
                                    #  -&gt; this one applies to your dims!
</code></pre>

<p>The only valid calls to imshow in your example are number 3 and 4 (while 1 and 2 are invalid)!</p>

<p>Listing:</p>

<ul>
<li><code>plt.imshow(img)</code> <strong>not ok</strong> as dtype=int64</li>
<li><code>plt.imshow(255-img)</code> <strong>not ok</strong> as dtype=int64</li>
<li><code>plt.imshow(np.uint8(img))</code> <strong>ok</strong> as dtype=uint8 (and compatible dims)</li>
<li><code>plt.imshow(img/255.0)</code> <strong>ok</strong> as dtype=float (and compatible dims)</li>
</ul>

<p><strong>Remark:</strong></p>

<p>If this makes you nervous, you could checkout <a href="http://scikit-image.org/" rel="nofollow">scikit-image</a> which is by design a bit more cautious about the internal representation of images (during custom-modifications and the resulting types). The internal data-structures are still numpy-arrays!</p>

python matplotlib