Some indices in indexed images made with cmunique are 0, what does that really mean? Isn't is a bug? I cannot index a colormap with index=0. Documentation is contradictory.

8 views (last 30 days)
I transform RGB images to indexed images with cmunique. Some of the indices in the indexed image are 0. It is not mentioned in the help for cmunique, but there is a contradictory statement in the help for rgb2ind, bold in the abbreviated citation below:
"[X,map] = rgb2ind(RGB,n) : Indexed image, returned as an m-by-n matrix X of nonnegative integers. If the length of map is less than or equal to 256, then the output image is of class uint8. Otherwise, the output image is of class uint16. n must be less than or equal to 65,536.
The value 0 in the output array X corresponds to the first color in the colormap."
In my case, the length of smallest color map is of the order of ~1500, so uint16 indices are expected. What do I do with elements of X that are 0 (zero), is there a way to prevent this happening?
Here is my relevant code:
% code snippet
Afull=imread('myfigure.png'); % myfigure.png is a color image
rectf=[133 56 521 521];
[fig_xrefout,fig_yrefout,Imfig,rectfig] = imcrop(Afull,rectf);
[Imfig_indexed,fig_map] =cmunique(Imfig);
dum=find(Imfig_indexed<=0);
~isempty(dum) % is 1!!!
  1 Comment
Stephen23
Stephen23 on 11 Sep 2024
Edited: Stephen23 on 11 Sep 2024
It is worth noting that the standard for indexed images is that 0 refers to the first color in the colormap. MATLAB must comply with this otherwise e.g. a standard 256 color indexed image would not be possible to import without messing up the data type or losing colors. Lets try with this internet-sourced 256 color indexed image:
fnm = 'Adaptative_8bits_palette_sample_image.png';
MATLAB tells us that this image contains a colormap with 256 colors, and that the (integer) image data uses 8 bits:
imfinfo(fnm)
ans = struct with fields:
Filename: '/users/mss.system.kt5vf/Adaptative_8bits_palette_sample_image.png' FileModDate: '11-Sep-2024 18:16:29' FileSize: 18263 Format: 'png' FormatVersion: [] Width: 150 Height: 200 BitDepth: 8 ColorType: 'indexed' FormatSignature: [137 80 78 71 13 10 26 10] Colormap: [256x3 double] Histogram: [] InterlaceType: 'none' Transparency: 'none' SimpleTransparencyData: [] BackgroundColor: [] RenderingIntent: [] Chromaticities: [] Gamma: [] XResolution: [] YResolution: [] ResolutionUnit: [] XOffset: [] YOffset: [] OffsetUnit: [] SignificantBits: [] ImageModTime: [] Title: [] Author: [] Description: [] Copyright: [] CreationTime: [] Software: [] Disclaimer: [] Warning: [] Source: [] Comment: [] OtherText: []
Lets get the image (i.e. index) and colormap:
[A,map] = imread(fnm)
A = 200x150
255 255 255 254 254 254 254 254 254 254 255 255 255 255 255 255 254 253 255 255 255 255 255 255 255 255 254 253 253 254 255 255 255 254 255 254 254 254 255 255 255 255 255 255 255 254 253 253 253 255 255 255 255 255 255 255 254 253 253 254 254 254 255 255 255 254 254 254 255 255 255 255 254 254 254 254 253 253 253 254 255 255 255 255 255 255 254 253 253 254 253 253 253 255 255 254 254 255 255 255 255 255 254 255 255 255 255 255 254 254 254 254 255 255 255 254 253 253 253 253 254 253 253 254 255 254 255 255 255 254 254 254 254 255 255 255 255 255 255 255 255 255 255 255 254 253 253 253 253 254 255 254 254 255 255 255 255 255 254 253 253 253 254 254 255 254 255 255 255 255 255 255 255 255 255 253 253 255 255 255 254 255 255 255 255 254 254 255 255 254 254 254 254 254 255 253 251 253 254 255 255 255 255 255 254 253 253 254 254 255 254 254 255 255 253 253 253 255 255 254 254 254 253 254 255 253 246 247 254 255 255 255 255 255 253 253 253 253 254 255 254 255 255 254 253 253 253 255 254 253 254 255 254 254 255 254 253 253 253 255 255 255 255 253 253 253 253 253 254 254 254 254 254 253 253 251 253 253 253 253 255 255 254 255 255 254 254 253 253 255 255 255 254 253 253 253 254 253 254 255
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
map = 256x3
1.0000 1.0000 1.0000 0.9647 0.9137 0.9373 0.9686 0.9412 0.8196 0.9373 0.8431 0.9137 0.9373 0.8196 0.8275 0.8118 0.9255 0.9529 0.7686 0.8863 0.8157 0.8314 0.7961 0.8235 0.9725 0.9529 0.6863 0.9725 0.9529 0.5608
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
class(A)
ans = 'uint8'
min(A(:))
ans = uint8 0
So the lowest index/value in that image is 0. But does this actually correspond to a color? It must otherwise there would be no way for a uint8 index to distinguish all 256 colors from that colormap. But lets check it anyway: we make the first row some easily distinguishable color and make the first few pixels 0:
A(1:20,1:20) = 0;
map(1,:) = [0,1,1]; % cyan
imshow(A,map)
Which means that the MATLAB documentation here:
is wrong: "...such that the value 1 points to the first row in map, the value 2 points to the second row, and so on".

Sign in to comment.

Answers (1)

Steven Lord
Steven Lord on 11 Sep 2024
0 is a nonnegative integer value.
isZeroNegative = 0 < 0 % false
isZeroNegative = logical
0
isZeroInteger = 0 == round(0) % true
isZeroInteger = logical
1
If you're using Imfig_indexed to directly index into fig_map then you would need to add 1 because 0 is not a valid index into an array in MATLAB.
If you're using this data in the context of displaying the image in MATLAB using image or the like, then by the default way color data values are mapped into the rows of the colormap (controlled by the CDataMapping property of the image object) this is correct. From that documentation page for the default value of the CDataMapping property, 'direct':
  • If the values are of type double or single, then values of 1 or less map to the first color in the colormap. Values equal to or greater than the length of the colormap map to the last color in the colormap.
  • If the values are of type uint8, uint16, uint32, uint64 , int8, int16, int32, or int64, then values of 0 or less map to the first color in the colormap. Values equal to or greater than the length of the colormap map to the last color in the colormap (or up to the range limits of the type).
  • If the values are of type logical, then values of 0 map to the first color in the colormap and values of 1 map to the second color in the colormap.
[Emphasis added.]
  3 Comments
Walter Roberson
Walter Roberson on 12 Sep 2024
XIndexed image
m-by-n matrix of integers
Indexed image, specified as an m-by-n matrix of integers.
  • If you specify X as an array of integer data type, then the value 0 corresponds to the first color in the colormap map. For a colormap containing c colors, values of image X are clipped to the range [0, c-1].
  • If you specify X as an array of data type single or double, then the value 1 corresponds to the first color in the colormap. For a colormap containing c colors, values of image X are clipped to the range [1, c].

Sign in to comment.

Products


Release

R2016b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!