1

This question is in continuation of the solution provided by tcaswell (answer #2) for my question: Is there a way to convert pyplot.imshow() object to numpy array?

Consider the following python code:

import pylab
import numpy as np

a = np.array( ( 30, 129 ) , dtype = np.float32 )
b = np.array( ( 30, 129 ) , dtype = np.int32 )
my_cm = pylab.cm.get_cmap('jet')
a_mapped_data = my_cm( a )
b_mapped_data = my_cm( b )

I am using a small array to save space, but this is what is seen even when large arrays are used.

The results:

>>> a
array([  30.,  129.], dtype=float32)

>>> b
array([ 30, 129])

>>> a_mapped_data
array([[ 0.5,  0. ,  0. ,  1. ],
       [ 0.5,  0. ,  0. ,  1. ]])

>>> b_mapped_data
array([[ 0.        ,  0.        ,  1.        ,  1.        ],
       [ 0.5028463 ,  1.        ,  0.46489564,  1.        ]])

I don't seem to understand the behavior here. Even though the values are same, cm.get_map() instance is producing different results for numpy.int32 and numpy.float32 data types. Is there something wrong with the code above? Please help out with this. I need to plot 2D arrays of type numpy.float.

Thank you

I am using python 2.7.3 32bit on Windows7 x64 Home Basic


EDIT : Solution for those who are facing the same problem as I did

The script below performs a color map on the input data and the map is converted to image as is, without using pylab.imshow or pylab.pcolor and without any scales or borders. I thank everyone contributed and helped me understand on how it can be done.

import pylab
import numpy as np

a = np.random.random( (512, 512) )*100
# a is a 2D array of random data not in the range of 0.0 to 1.0

# normalize the data
normed_a = ( a - a.min() )/( a.max() - a.min() )

# now create an instance of pylab.cm.get_cmap()
my_cm = pylab.cm.get_cmap('jet_r')

# create the map
mapped_a = my_cm( normed_a )

# to display the map, opencv is being used
# import opencv
import cv2 as cv

# convert mapped data to 8 bit unsigned int
mapped_au8 = (255 * mapped_a).astype('uint8')

# show the image
cv.imshow( 'a', mapped_au8 )
cv.waitKey( 0 )
cv.destroyAllWindows()

EDIT : Return type cm.get_cmap instance is of RGBA format but OpenCV by default operates on BGR format. Hence before displaying any image obtained by converting return values of cm.get_cmap() instance as in the above code, convert it to BGR format ( The ALPHA channel is anyway stripped by default in opencv before the image is displayed so dont bother to convert it into BGRA unless necessary ). The code below gives a better explanation:

mapped_au8 = (255 * mapped_a).astype('uint8')

#convert mapped_au8 into BGR fromat before display
mapped_u8 = cv.cvtColor( mapped_au8, cv.COLOR_RGBA2BGR )

# show the image
cv.imshow( 'a', mapped_au8 )
cv.waitKey( 0 )
cv.destroyAllWindows()
Community
  • 1
  • 1
Yash
  • 659
  • 4
  • 11
  • 25

1 Answers1

2

From the docstring of my_cm.__call__:

*X* is either a scalar or an array (of any dimension).
If scalar, a tuple of rgba values is returned, otherwise
an array with the new shape = oldshape+(4,). If the X-values
are integers, then they are used as indices into the array.
If they are floating point, then they must be in the
interval (0.0, 1.0).
Alpha must be a scalar between 0 and 1, or None.
If bytes is False, the rgba values will be floats on a
0-1 scale; if True, they will be uint8, 0-255.

Note the difference between how floats and ints are treated.

Warren Weckesser
  • 102,583
  • 19
  • 173
  • 194
  • So if have an array like `[12.02, 1.122][0.23, 7.543]` can i divide the entire array with the largest place value applicable (in this case 100) and plot it? It should produce right results, right? – Yash Feb 14 '13 at 17:54
  • Well, I tried dividing by the largest place value. It don't think it gives the right result..... – Yash Feb 14 '13 at 18:30
  • what do you mean place value? – tacaswell Feb 14 '13 at 18:39
  • 1
    Maybe `s = (a - a.min()) / a.ptp(); a_mapped = my_cm(s)`; that linearly maps the data to the interval [0,1]. – Warren Weckesser Feb 14 '13 at 18:40
  • 1
    @Yash gah, sorry I messed up. Fixed my other answer. – tacaswell Feb 14 '13 at 18:47
  • @tcaswell: i mean decimal place value – Yash Feb 14 '13 at 19:06
  • @tcaswell: i meant decimal place value. I just wanted to normalize the values which was later suggested by WarrenWeckesser in a better way. I saw your fix in the previous answer too. I am now getting exactly what wanted. Thank you for taking out your time to answer my questions. – Yash Feb 14 '13 at 19:13
  • @WarrenWeckesser: Thank you for your input. It worked. Thank you for taking your time to answer my question. – Yash Feb 14 '13 at 19:14