1

From a rgb image another one was made only by adding borders filled with zero: enter image description here

Densitometric profiles show that the pixel values are the same for non zero domain on both images

subplot(141)
imshow(rgb_chromosomes[0])
subplot(142)
plot(rgb_chromosomes[0][13,:,:])
subplot(143)
imshow(resized_rgb[0][10:40,11:40,:])
subplot(144)
plot(resized_rgb[0][25,17:38,:])

show()

It is weird that the resized image looks blue, whereas the original one looks brown. What to do such that the second image look like the first one?

Thanks

Jean-Pat
  • 1,839
  • 4
  • 24
  • 41
  • 2
    check your data types. ints are assumed to be in range [0, 256), floats are assumed to be in [0, 1] and does not explicitly check these assumptions. also, please don't sign your posts, your user block is already at the bottom. – tacaswell Feb 18 '14 at 15:14
  • The dtype of the new image,resized_rgb[0], is float64 ! But if I do plot(np.uint8(resized_rgb[0][25,17:38,:])), the image is still blue ... – Jean-Pat Feb 18 '14 at 16:07
  • The image type is ok now. Thank you! – Jean-Pat Feb 18 '14 at 16:15
  • 1
    Can you write an answer explaining how you fixed it? (and then accept it when SO will let you). – tacaswell Feb 18 '14 at 16:16
  • There's a function called ResizeImages() here http://bit.ly/1dICsaQ (A sagemath cloud project). The problem was fixed by specifying the dtype value of the following image: newIm=np.zeros((maxheight,maxwidth,components), dtype=imtype). A smaller image is then pasted in that bigger one: newIm[starth:starth+height,startw:startw+width,:]=ImList[i][:,:,:] . Since the small one is uint8, the new one is uint8 too. – Jean-Pat Feb 18 '14 at 19:51
  • as an actual answer, not a comment please. This is so a) it is more persistent b) you can get rep for your answer ;) – tacaswell Feb 18 '14 at 19:54

2 Answers2

3

Suppose you have a list of rgb images, that is a stack of 3 numpy arrays of uint8, and you need to add borders so that all the images have the same shape. the following function does the job:

def ResizeImages(ImList):
        '''Find the largest width and height of images belonging to a list.
        Return a list of images of same width/height
        '''
        maxwidth=0
        maxheight=0
        components = np.shape(ImList[0])[2]
        imtype = ImList[0].dtype
        for i in range(len(ImList)):
            width=np.shape(ImList[i])[1]#width=column
            height=np.shape(ImList[i])[0]#height=line
            #print "width:height",width,":",height
            if width>maxwidth:maxwidth=width
            if height>maxheight:maxheight=height
        #print "maxwidth:maxheight",maxwidth,":",maxheight                
        NewList=[]
        for i in range(0,len(ImList)):
            width=np.shape(ImList[i])[1]
            height=np.shape(ImList[i])[0]

            diffw=maxwidth-width
            startw=round(diffw/2)
            diffh=maxheight-height
            starth=int(round(diffh/2))
            startw=int(round(diffw/2))

            newIm=np.zeros((maxheight,maxwidth,components), dtype=imtype)
            newIm[starth:starth+height,startw:startw+width,:]=ImList[i][:,:,:]
            NewList.append(newIm)
        return NewList

Each image to be resized is pasted in an image first filled with zero of type dtype=uint8 (since uint8 arrays are sent in the function):

newIm=np.zeros((maxheight,maxwidth,components), dtype=imtype)
newIm[starth:starth+height,startw:startw+width,:]=ImList[i][:,:,:]

The bug was here:

newIm=np.zeros((maxheight,maxwidth,components))

Since no type was specified the type by default was float64, explaining why the color of the resized images looks weird.

Jean-Pat
  • 1,839
  • 4
  • 24
  • 41
2

See Imshow subplots with the same colorbar and Set Colorbar Range in matplotlib.

If you use the same vmin/vmax and cmap in all calls to imshow, the colors should reflect the exact same intensities, regardless of the overall range in the image.

Edit: added example after comments. It's possible that I've misinterpreted what the problem is but the code/image illustrate how the v limits can be set to match colors (top row) or what happens if each image is automatically normalised (bottom row).

import numpy as np
import matplotlib.pyplot as plt 
import matplotlib.cm as cm

offset = 5.5

x1 = np.random.rand(12,16) + offset
x2 = np.array(x1)
x2 = np.zeros((15, 20))
x2[2:2+x1.shape[0], 3:3+x1.shape[1]] = x1

vmin = x1.min()
vmax = x1.max()

cmap = cm.hot

plt.figure(1); plt.clf()
f, ax = plt.subplots(2,2, num=1)

im0 = ax[0,0].imshow(x1, interpolation='nearest', cmap=cmap, vmin=vmin, vmax=vmax)
f.colorbar(im0, ax=ax[0,0])

im1 = ax[0,1].imshow(x2, interpolation='nearest', cmap=cmap, vmin=vmin, vmax=vmax)
f.colorbar(im1, ax=ax[0,1])
ax[0,1].set_title('image with border, sharing v lims')

im2 = ax[1,0].imshow(x1, interpolation='nearest', cmap=cmap)
f.colorbar(im2, ax=ax[1,0])

im3 = ax[1,1].imshow(x2, interpolation='nearest', cmap=cmap)
f.colorbar(im3, ax=ax[1,1])
ax[1,1].set_title('image with border, own v lims')

f.show()

the effect of sharing limits

Note: the problem only manifests when the nonzero color range does not include zero. That is shown with the offset variable above.

Community
  • 1
  • 1
Bonlenfum
  • 19,101
  • 2
  • 53
  • 56
  • changing vmin / vmax (cmap=pylab.cm.Greys_r/Greys) have no effect on a color image – Jean-Pat Feb 18 '14 at 13:48
  • I don't understand your comment. Are you suggesting that setting these values cannot affect color images, or that they don't affect your image? I've added some example code that might help resolve it? – Bonlenfum Feb 18 '14 at 14:27
  • Modifying the value of vmax for example doesn't affect the way the image is displayed. Watching your code, I notice that x2 is a monochromatic image: np.shape(x2) gives (15,20) whereas the images in my example are rgb image that is stack of 3 numpy array, their dimension is for example (47,54,3) – Jean-Pat Feb 18 '14 at 14:53
  • the colormap is only used when scalar arrays are passed in, if mxnx[3,4] arrays are passed in the colors are used directly. – tacaswell Feb 18 '14 at 15:11
  • Ah good spot! I see that the [imshow docs](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.imshow) do state that although I missed it before. It doesn't offer any suggestions for artificial coloring in this case sadly. This [mpl tutorial](http://matplotlib.org/1.3.1/users/image_tutorial.html#applying-pseudocolor-schemes-to-image-plots) suggests using pseudo-colors, by taking one of the dimensions only (or obviously blending rgb->greyscale). But that might not be appropriate for your data. – Bonlenfum Feb 18 '14 at 15:12