Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Single channel png displayed with colors

Tags:

I'm checking out the ground truth segmentation masks of the pascal voc 2012 dataset. These are single channel 8-bit uint png files. However when I open these images in either the file browser (nautilus) or the image viewer (eog) they are displayed in colors.
Shouldn't it be displayed in grayscale?
When I store an image as single channel 8-bit uint png file using Matlab, it is displayed in grayscale as expected. What is the difference are there different types of png files?
How can I store it such that my image viewer displays them in colors?

This is the original single channel png:
this is the original single channel png

This is the result after imread and imwrite. Note that NO channel has been added / removed:
this is the result after <code>imread</code> and <code>imwrite</code> NO channel had been added / removed

like image 937
mcExchange Avatar asked Nov 22 '17 15:11

mcExchange


2 Answers

Your image files contain indexed images, with an M-by-N index matrix and a P-by-3 colormap matrix. How can you tell? You need to get the second output from imread when loading your images:

[img, cmap] = imread('zuIra.png');
if isempty(cmap)
  % Process data as a grayscale or RGB image
else
  % Process data as an indexed image
end

If cmap is empty, your data is either an M-by-N grayscale intensity image or an M-by-N-by-3 Truecolor RGB image. Otherwise, you're dealing with an indexed color image, and will have to use both pieces of data in any processing of your image, such as viewing it with imshow:

imshow(img, cmap);

Or when resaving the data with imwrite:

imwrite(img, cmap, 'outfile.png');

If you would rather deal with a single image data matrix (which can make processing easier in some cases), you can convert the indexed image data and associated colormap into an RGB image with ind2rgb:

imgRGB = ind2rgb(img, cmap);
like image 198
gnovice Avatar answered Sep 21 '22 12:09

gnovice


You are dealing with an 1 to 8 bits (variable) per pixel PNG with indexed colors.

When a format uses this technique, color information is not directly stored into the the image pixel data, but in a separate piece of data called palette. A palette can be defined as a predefined array of colors in which each element defines the trichromatic representation (RGB) of a specific color (8 bits per channel, for a total of 24 bits).

The image pixel data does not contain the full specification of a color in the RGB form, but only the indices to the palette colors. Of course, the palette must contain one entry for each pixel color present in the image.

This approach can be seen as a form of compression, in which only a limited set of colors is available in order to save up memory/storage and speed up the display of the image.

Long story short, the result of your imread call is not returning you the color information of the image. Your array contains the indices to the PNG palette elements.

Example

Let's say that you have n indexed PNG that has a width of 3 pixels and a height of 1 pixel. The first pixel is pure red, the second pixel is pure green and the third pixel is pure blue.

In the PNG binary data, the PLTE chunk will contain the following color definitions:

[255 0 0] % Pure Red
[0 255 0] % Pure Green
[0 0 255] % Pure Blue

and the IHDR chunk will define a single channel with the following data:

0 1 2

% 0 = index to the first palette color, pure red
% 1 = index to the second palette color, pure green
% 2 = index to the third palette color, pure blue
like image 43
Tommaso Belluzzo Avatar answered Sep 20 '22 12:09

Tommaso Belluzzo