Python - greyscale image to 3 channels
Clash Royale CLAN TAG#URR8PPP
Python - greyscale image to 3 channels
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'>
Have you tried
gray2rgb
? scikit-image.org/docs/dev/api/…– Håken Lid
Aug 11 at 23:05
gray2rgb
3 Answers
3
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).
max()
dtype
"u16"
"int32"
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.
norm
imshow
inverse
Thanks, will try. Can you please elaborate a bit on the dtype stuff? Also, do you have any logical explanation as to why my original attempt doesn't work?
– Baron Yugovich
Aug 12 at 1:25
I tried test_image = skimage.color.gray2rgb(test_image), I get a white image with some rare small black dots, doesn't work.
– Baron Yugovich
Aug 12 at 1:27
dtype
sets the numeric data type used inside the array. You may want to pay special attention to that. Try printing the type of the sample values before and after the conversion to make sure something didn't change radically. 2D: print type(test_image[0,0])
3D: print type(test_image[0,0,0])
– nobar
Aug 12 at 1:30
dtype
print type(test_image[0,0])
print type(test_image[0,0,0])
The imshow docs say
cmap is ignored if X is 3-D, directly specifying RGB(A) values.
This is my guess as to why you aren't seeing something sensible. See what happens if you invert the image.– nobar
Aug 12 at 1:35
cmap is ignored if X is 3-D, directly specifying RGB(A) values.
How would I invert the image, what is the exact command? Also, please see the edits I made to the original question above.
– Baron Yugovich
Aug 12 at 1:36
Your conversion from gray-value to RGB by replicating the gray-value three times such that R==G==B
is correct.
R==G==B
The strange displayed result is likely caused by assumptions made during display. You will need to scale your data before display to fix it.
Usually, a uint8 image has values 0-255, which are mapped to min-max scale of display. Uint16 has values 0-65535, with 65535 mapped to max. Floating-point images are very often assumed to be in the range 0-1, with 1 mapped to max. Any larger value will then also be mapped to max. This is why you see so much white in your output image.
If you divide each output sample by the maximum value in your image you’ll be able to display it properly.
Well, imshow is using by default, a kind of heatmap to display the image intensities. To display a grayscale image just specify the colormap as above:
plt.imshow(image, cmap="gray")
Now, i think you can get the channel of an image by doing:
image[:,:,i] where i is in 0,1,2
To extract an image for a specific channel:
red_image = image.copy()
red_image[:,:,1] = 0
red_image[:,:,2] = 0
Edit:
Do you definitely have to use skimage? What about python-opencv module?
Have you tried the following example?
import cv2
import cv
color_img = cv2.cvtColor(gray_img, cv.CV_GRAY2RGB)
Sorry, I am asking how to transform a 1 channel image into a 3 channel image that looks reasonable when plotted.
– Baron Yugovich
Aug 11 at 22:51
Ok sorry, see my updated answer. Also have you tried to plot the 3-channel image using a colormap to see if it makes sense?
– curi0uz_k0d3r
Aug 12 at 6:20
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
It (probably) comes out colored because you did not set a colormap and the default is somewhat a bad choice here. Nobody can tell you how to magically derive colors for some NN which is unknown, as most NNs used for natural colors will fail completely with this one.
– sascha
Aug 11 at 21:29