matplotlib imshow plots different if using colormap or RGB array
matplotlib, numpy, python
Solution
I find the right plot much more artistic...
`matplotlib` is rather complicated when it comes to interpreting images. It goes roughly as follows:
if the image is a NxM array of any type, it is interpreted through the colormap (autoscale, if not indicated otherwise). (In principle, if the array is a `float` array scaled to 0..1, it should be interpreted as a grayscale image. This is what the documentation says, but in practice this does not happen.)
if the image is a NxMx3 `float` array, the RGB components are interpreted as RGB components between 0..1. If the values are outside of this range, they are taken with positive modulo 1, i.e. 1.2 -> 0.2, -1.7 -> 0.3, etc.
if the image is a NxMx3 `uint8` array, it is interpreted as a standard image (0..255 components)
if the image is NxMx4, the interpretation is as above, but the fourth component is the opacity (alpha)
So, if you give `matplotlib` a NxMx3 array of integers other than `uint8` or `float`, the results are not defined. However, by looking at the source code, the odd behavour can be understood:
if A.dtype != np.uint8:
A = (255*A).astype(np.uint8)
where `A` is the image array. So, if you give it `uint16` values 0, 1, 2, 3, 4..., you get 0, 255, 254, 253, ... Yes, it will look very odd. (IMHO, the interpretation could be a bit more intuitive, but this is how it is done.)
In this case the easiest solution is to divide the array by 65535., and then the image should be as expected. Also, if your original image is truly linear, then you'll need to make the reverse gamma correction:
img1_corr = (img1 / 65535.)**(1/2.2)
Otherwise your middle tones will be too dark.
Problem
I am having the following problem: I am saving 16-bit tiff images with a microscope and I need to analyze them. I want to do that with numpy and matplotlib, but when I want to do something as simple as plotting the image in green (I will later need to superpose other images), it fails. Here is an example when I try to plot the image either as a RGB array, or with the default `jet` colormap. ``` import numpy as np import matplotlib.pyplot as plt import cv2 imageName = 'image.tif' # image as luminance img1 = cv2.imread(imageName,-1) # image as RGB array shape = (img1.shape[0], img1.shape[1], 3) img2 = np.zeros(shape,dtype='uint16') img2[...,1] += img1 fig = plt.figure(figsize=(20,8)) ax1 = fig.add_subplot(1,2,1) ax2 = fig.add_subplot(1,2,2) im1 = ax1.imshow(img1,interpolation='none') im2 = ax2.imshow(img2,interpolation='none') fig.show() ``` Which to me yields the following figure: I am sorry if the question is too basic, but I have no idea why the right plot is showing this artifacts. I would like to get with the green scale, something like how the figure looks (imageJ also yields somthing similar to the left plot). Thank you very much for your collaboration.