Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

matplotlib imshow plots different if using colormap or RGB array

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: enter image description here

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.

like image 428
Antonio Yanez Santamaria Avatar asked Jul 14 '14 15:07

Antonio Yanez Santamaria


People also ask

How do I change my color on Imshow?

The most direct way is to just render your array to RGB using the colormap, and then change the pixels you want.

Does Imshow normalize?

By default, imshow normalizes the data to its min and max. You can control this with either the vmin and vmax arguments or with the norm argument (if you want a non-linear scaling).

How do I show the RGB image in Matplotlib?

Tutorial: How to Display a Matplotlib RGB ImageA simple call to the imread method loads our image as a multi-dimensional NumPy array (one for each Red, Green, and Blue component, respectively) and imshow displays our image to our screen.

How does PLT Imshow work?

imshow. The matplotlib function imshow() creates an image from a 2-dimensional numpy array. The image will have one square for each element of the array. The color of each square is determined by the value of the corresponding array element and the color map used by imshow() .


1 Answers

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.

like image 150
DrV Avatar answered Oct 21 '22 13:10

DrV