Python - greyscale image to 3 channels

Baron Yugovich picture Baron Yugovich · Aug 11, 2018 · Viewed 8.5k times · Source

I have code that looks like this

from skimage import io as sio
test_image = imread('/home/username/pat/file.png')
test_image  = skimage.transform.resize(test_image, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True)
print test_image.shape # prints (128,128)
print test_image.max(), test_image.min() # prints 65535.0 0.0
sio.imshow(test_image)

More importantly, I need to make this image be in 3 channels, so I can feed it into a neural network that expects such input, any idea how to do that?

I want to transform a 1-channel image into a 3-channel image that looks reasonable when I plot it, makes sense, etc. How?

I tried padding with 0s, I tried copying the same values 3 times for the 3 channels, but then when I try to display the image, it looks like gibberish. So how can I transform the image into 3 channels, even if it becomes something like, bluescale instead of greyscale, but still be able to visualize it in a meaningful way?

Edit: if I try

test_image = skimage.color.gray2rgb(test_image)

I get all white image, with some black dots.

I get the same all white, rare small black dots if I try

convert Test1_PC_1.tif -colorspace sRGB -type truecolor Test1_PC_1_new.tif

Before the attempted transform with gray2rgb

print type(test_image[0,0])
<type 'numpy.uint16'>

After

print type(test_image[0,0,0])
<type 'numpy.float64'>

Answer

Brent Bradburn picture Brent Bradburn · Aug 12, 2018

You need to convert the array from 2D to 3D, where the third dimension is the color.

You can use the gray2rgb function function provided by skimage:

test_image = skimage.color.gray2rgb(test_image)

Alternatively, you can write your own conversion -- which gives you some flexibility to tweak the pixel values:

# basic conversion from gray to RGB encoding
test_image = np.array([[[s,s,s] for s in r] for r in test_image],dtype="u1")

# conversion from gray to RGB encoding -- putting the image in the green channel
test_image = np.array([[[0,s,0] for s in r] for r in test_image],dtype="u1")

I notice from your max() value, that you're using 16-bit sample values (which is uncommon). You'll want a different dtype, maybe "u16" or "int32". Also, you may need to play some games to make the image display with the correct polarity (it may appear with black/white reversed).

One way to get there is to just invert all of the pixel values:

test_image = 65535-test_image ## invert 16-bit pixels

Or you could look into the norm parameter to imshow, which appears to have an inverse function.