MATLAB imread() wrong gray scale - matlab

I made a simple grayscale image with paint.net:
Then I simply read the image using MATLAB imread() and got something like this (same thing for Octave):
I checked the background value and it's 55 instead of 255.
I then tried the same thing in Python using pyplot.imread() and get the expected result:
I saw this a couple of times even when I was reading something like Lena in MATLAB -- the gray scale was totally messed up. Does anyone know what's wrong with imread in MATLAB (and Octave)?

Your PNG image is an RGB image, not a gray-value image. It was saved as an indexed image, meaning that 56 different RGB values were stored in a table, and the image references those RGB values by specifying an index for each pixel.
The image you're seeing consists of the indices into the color table, not the actual RGB values saved.
You need to read both the indices and the color map as follows:
[img,cm] = imread('https://i.stack.imgur.com/rke2o.png');
Next, you can recover the original RGB image using ind2rgb, or, given that you are looking for a gray-value image, you can recover the gray-values using ind2gray:
img = ind2gray(img,cm);

Related

Gaussian kernel isn't showing up [duplicate]

I have imported an image. I have parsed it to double precision and performed some filtering on it.
When I plot the result with imshow, the double image is too dark. But when I use imshowpair to plot the original and the final image, both images are correctly displayed.
I have tried to use uint8, im2uint8, multiply by 255 and then use those functions, but the only way to obtain the correct image is using imshowpair.
What can I do?
It sounds like a problem where the majority of your intensities / colour data are outside the dynamic range of what is accepted for imshow when showing double data.
I also see that you're using im2double, but im2double simply converts the image to double and if the image is already double, nothing happens. It's probably because of the way you are filtering the images. Are you doing some sort of edge detection? The reason why you're getting dark images is probably because the majority of your intensities are negative, or are hovering around 0. imshow whe displaying double type images assumes that the dynamic range of intensities is [0,1].
Therefore, one way to resolve your problem is to do:
imshow(im,[]);
This shifts the display so that range so the smallest value is mapped to 0, and the largest to 1.
If you'd like a more permanent solution, consider creating a new output variable that does this for you:
out = (im - min(im(:))) / (max(im(:)) - min(im(:)));
This will perform the same shifting that imshow does when displaying data for you. You can now just do:
imshow(out);

Reading grayscale image in matlab [duplicate]

This question already has an answer here:
What does the index refer to when selecting a pixel on an image in Matlab?
(1 answer)
Closed 6 years ago.
I have gray scale image "lena.bmp". I want read this image in matlab using imread() function.
When i use code below to read and show image my image is dark (black).
img = imread('lena.bmp');
imshow(img);
But when i use code below, I have no problem to view.
[img map]= imread('lena.bmp');
imshow(img,map);
It seems that my first code doses not reading image in grayscale mode (like what rgb2gray function generate).
My image is as follows:
What can i do to solve this problem?
Your image is an "indexed" image. That means it contains integer values which act as "labels" more than anything, and each of those labels is mapped to a colour (i.e. an rgb triplet). Your map variable represents that mapping; at row 5 you have the rgb triplet that corresponds to 'label' "5", for instance.
To see what I mean, do unique(img) and you'll see that the values of your img array are in fact quite regular. The command rgbplot can demonstrate the actual colourmap graphically. Run rgbplot(map) on your map variable to see the mapping for each of the red green and blue colours.
Now, save and read the image below on your computer as img2 and compare the array values.
This image was generated by converting from the "indexed" image you linked to, to a "grayscale" one using photoediting software (the GIMP). The difference is that
in a grayscale image, the pixel values represent actual intensities, rather than integer 'labels'. Imread reads grayscale images as uint8 images by default, meaning it assigns intensity values to pixels ranging from 0 (black) to 255 (white). Since these values happen to be integers you could still cheat and treat them as 'labels' and force a colour-mapping on them. But if you assign a 'linear map' (i.e. value 1 = intensity 1, value 2 = intensity 2, etc) then your image will look as you would expect.
You'll see that the values from unique(img2) are quite different. If you imshow(img2) you'll see this displays as you'd expect. If you don't specify a colormap for imshow, it will assume that the map is a linear mapping from the lowest to the highest value in the image array, which explains why your indexed image looked weird, since its values were never supposed to correspond to intensities.
Also try imagesc(img2) which will show this but using the "current" colormap. imagesc causes the colormap to be "scaled", so that the lowest colour goes to the lowest value in the image, and similarly for the highest.
The default colormap is jet so you should see a psychedelic looking image but you should be able to make out lena clearly. If you try colormap gray you should see the gray version again. Also try colormap hot. Now to make sense of the colormaps, try the rgbplot command on them (e.g. rgbplot(gray), rgbplot(hot) etc).
So, going back to imshow, imshow basically allows you to display an indexed image, and specify what colormap you want to use to display it. If you don't specify the colormap, it will just use a linear interpolation from the lowest value to the highest as your map. Therefore imshow(img) will show the image pretty much in the same way as imagesc(img) with a gray colormap. And since the values in your first img represent evenly spaced 'labels' rather than actual intensities, you'll get a rubbish picture out.
EDIT: If you want to convert your indexed image to a grayscale image, matlab provides the ind2gray function, e.g.:
[img, map] = imread('lena.bmp');
img_gray = ind2gray(img, map);
This is probably what you need if you mean to process pixel values as intensities.

MATLAB imshow for 3D color image

I have a medical imaging matrix of size [200x200x200].
In order to display it, I am currently using imshow3D function, which is an excellent tool, built by Maysam Shahedi.
This tool displays the 3D image slice by slice, with mouse based slice browsing
In my current project, I generate an RGB image for each z-layer from the original input image. The output is a 3D color image of size [200x200x200x3] (each layer is now represented by 3 channels).
The imshow3D function works great on grayscale images. Is it possible to use it to display RGB images?
I took a look at this nice imshow3D function from Matlab FileExchange, and it is quite straight-forward to change it to allow working with a stack of RGB images.
The magic part of the function is
imshow(Img(:,:,S))
which displays the slice S of the image Img. We can simply change it to show all 3 channels of image S by changing this to Img(:,:,S,:). The result will be of size 200-by-200-by-1-by-3, while MATLAB expects RGB images to be of size 200-by-200-by-3. Simply squeeze this image to get the correct dimension. This results in:
imshow(squeeze(Img(:,:,S,:))
So to show RGB images, do a search-and-replace inside the function imshow3D, to replace all occurrences of Img(:,:,S) with squeeze(Img(:,:,S,:)) and it works!

Colormap and GIF images in Matlab

I have a problem understanding colormaps in Matlab and using them to import and diplay .gif images.
I would like to import an image using
im = imread('I.gif')
and then display it using
imshow(im)
but the result is wrong
If I do
[im,map] = imread('I.gif')
and then display it using
imshow(im,map)
it works properly, but still I don't understand the need of this colormap
Is there a way to import and convert my gif image to greyscale so that when I do
imshow(im)
it shows the correct greyscale image without having to worry about the colormap?
SOrry for the noob question but I am just starting with image processing in Matlab and I would really appreciate some help. It is my first question! :)
Bye and thanks!
If you want to convert your gif to grayscale, use ind2gray:
[im,map] = imread('I.gif');
imGray = ind2gray(im,map);
The reason that you need the colormap is that the gif format doesn't store image intensities, it stores indices into the colormap. So color 0 could be red or green or a very light shade of mauve. It's the colormap that stores the actual RGB colors that the image needs. ind2gray will take each of those colors, convert them to a grayscale intensity, and replace the indices in the image with those intensities.
It looks like you've really already answered the question. It seems that .gif files support an indexed color format, as a way of saving space. See:
https://en.wikipedia.org/wiki/Indexed_color
This is different than a more typical RGB color, which is what is often received from an IMREAD call.
To convert to a grayscale, you would need to go through the colormap and assign a grayscale value to each color, and then substitute those values back into the im variable.

Working with tiff's in matlab

How do find out what bit a file is? I have a tiff and convert it to class double to work with the values in the command line. When I do that though the histogram (256 bins) looks like it is binary when that isn't the case for the original file. Why is that? How do I correct that? Another odd thing is the image that I get isnt binary, you can actually see different shades of gray.
Im not sure I understood the problem but to get a detailed information of an image file, use the IMFINFO function
I assume that you converted the image to double using IM2DOUBLE. This rescales the image so that its values are distributed between 0 and 1 (for example, the pixel values of an 8-bit image would be divided by 255).
If you were to plot the histogram with hist(img(:),(0:255)/255), where img is the converted image, you'd see the 256 bins as you'd expect them.