[07d29c]: cmunique.m Maximize Restore History

Download this file

cmunique.m    204 lines (176 with data), 6.6 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
## Copyright (C) 2004 Josep Mones i Teixidor
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
## -*- texinfo -*-
## @deftypefn {Function File} {[@var{Y}, @var{newmap}] = } cmunique (@var{X},@var{map})
## @deftypefnx {Function File} {[@var{Y}, @var{newmap}] = } cmunique (@var{RGB})
## @deftypefnx {Function File} {[@var{Y}, @var{newmap}] = } cmunique (@var{I})
## Finds colormap with unique colors and corresponding image
##
## @code{[Y,newmap]=cmunique(X,map)} returns an indexed image @var{y}
## along with its associated colormap @var{newmap} equivalent (which
## produce the same image) to supplied @var{X} and its colormap
## @var{map}; but eliminating any repeated rows in colormap colors and
## adjusting indices in the image matrix as needed.
##
## @code{[Y,newmap]=cmunique(RGB)} returns an indexed image @var{y}
## along with its associated colormap @var{newmap} computed from a
## true-color image @var{RGB} (a m-by-n-by-3 array), where @var{newmap}
## is the smallest colormap possible (alhough it could be as long as
## number of pixels in image).
##
## @code{[Y,newmap]=cmunique(I)} returns an indexed image @var{y}
## along with its associated colormap @var{newmap} computed from a
## intensity image @var{I}, where @var{newmap} is the smallest
## colormap possible (alhough it could be as long as number of pixels
## in image).
##
## @strong{Notes:}
##
## @var{newmap} is always a @var{m}-by-3 matrix, even if input image is
## a intensity grey-scale image @var{I} (all three RGB planes are
## assigned the same value).
##
## @var{newmap} is always of class double. If we use a RGB or intensity
## image of class uint8 or uint16, the colors in the colormap will be of
## class double in the range [0,1] (they are divided by intmax("uint8")
## and intmax("uint16") respectively.
##
## @end deftypefn
## Author: Josep Mones i Teixidor <jmones@puntbarra.com>
function [Y, newmap] = cmunique(P1, P2)
if (nargin<1 || nargin>2)
usage("[Y, newmap] = cmunique(X, map), [Y, newmap] = cmunique(RGB), [Y, newmap] = cmunique(I)");
endif
if(nargin==2)
## (X, map) case
[newmap,i,j]=unique(P2,'rows'); ## calculate unique colormap
if(isa(P1,"double"))
Y=j(P1); ## find new indices
else
Y=j(double(P1)+1); ## find new indices
endif
else
switch(size(P1,3))
case(1)
## I case
[newmap,i,j]=unique(P1); ## calculate unique colormap
newmap=repmat(newmap,1,3); ## get a RGB colormap
Y=reshape(j,rows(P1),columns(P1)); ## Y is j reshaped
case(3)
## RGB case
map=[P1(:,:,1)(:), P1(:,:,2)(:), P1(:,:,3)(:)]; ## build a map with all values
[newmap,i,j]=unique(map, 'rows'); ## calculate unique colormap
Y=reshape(j,rows(P1),columns(P1)); ## Y is j reshaped
otherwise
error("cmunique: first parameter is invalid.");
endswitch
## if image was uint8 or uint16 we have to convert newmap to [0,1] range
if(!isa(P1,"double"))
newmap=double(newmap)/double(intmax(class(P1)));
endif
endif
if(rows(newmap)<=256)
## convert Y to uint8 (0-based indices then)
Y=uint8(Y-1);
endif
endfunction
%!demo
%! [Y,newmap]=cmunique([1:4;5:8],[hot(4);hot(4)])
%! # Both rows are equal since map maps colors to the same value
%! # cmunique will give the same indices to both
%!# This triggers invalid first parameter
%!error(cmunique(zeros(3,3,2)));
%!# Check that output is uint8 in short colormaps
%!test
%! [Y,newmap]=cmunique([1:4;5:8], [hot(4);hot(4)]);
%! assert(Y,uint8([0:3;0:3]));
%! assert(newmap,hot(4));
%!# Check that output is double in bigger
%!test
%! [Y,newmap]=cmunique([1:300;301:600], [hot(300);hot(300)]);
%! assert(Y,[1:300;1:300]);
%! assert(newmap,hot(300));
%!# Check boundary case 256
%!test
%! [Y,newmap]=cmunique([1:256;257:512], [hot(256);hot(256)]);
%! assert(Y,uint8([0:255;0:255]));
%! assert(newmap,hot(256));
%!# Check boundary case 257
%!test
%! [Y,newmap]=cmunique([1:257;258:514], [hot(257);hot(257)]);
%! assert(Y,[1:257;1:257]);
%! assert(newmap,hot(257));
%!# Random RGB image
%!test
%! RGB=rand(10,10,3);
%! [Y,newmap]=cmunique(RGB);
%! assert(RGB(:,:,1),newmap(:,1)(Y+1));
%! assert(RGB(:,:,2),newmap(:,2)(Y+1));
%! assert(RGB(:,:,3),newmap(:,3)(Y+1));
%!# Random uint8 RGB image
%!test
%! RGB=uint8(rand(10,10,3)*255);
%! RGBd=double(RGB)/255;
%! [Y,newmap]=cmunique(RGB);
%! assert(RGBd(:,:,1),newmap(:,1)(Y+1));
%! assert(RGBd(:,:,2),newmap(:,2)(Y+1));
%! assert(RGBd(:,:,3),newmap(:,3)(Y+1));
%!# Random uint16 RGB image
%!test
%! RGB=uint16(rand(10,10,3)*65535);
%! RGBd=double(RGB)/65535;
%! [Y,newmap]=cmunique(RGB);
%! assert(RGBd(:,:,1),newmap(:,1)(Y+1));
%! assert(RGBd(:,:,2),newmap(:,2)(Y+1));
%! assert(RGBd(:,:,3),newmap(:,3)(Y+1));
%!# Random I image
%!test
%! I=rand(10,10);
%! [Y,newmap]=cmunique(I);
%! assert(I,newmap(:,1)(Y+1));
%! assert(I,newmap(:,2)(Y+1));
%! assert(I,newmap(:,3)(Y+1));
%!# Random uint8 I image
%!test
%! I=uint8(rand(10,10)*256);
%! Id=double(I)/255;
%! [Y,newmap]=cmunique(I);
%! assert(Id,newmap(:,1)(Y+1));
%! assert(Id,newmap(:,2)(Y+1));
%! assert(Id,newmap(:,3)(Y+1));
%!# Random uint16 I image
%!test
%! I=uint16(rand(10,10)*65535);
%! Id=double(I)/65535;
%! [Y,newmap]=cmunique(I);
%! assert(Id,newmap(:,1)(Y+1));
%! assert(Id,newmap(:,2)(Y+1));
%! assert(Id,newmap(:,3)(Y+1));
%
% $Log$
% Revision 1.4 2004/09/08 16:06:31 jmones
% Solved problem with uint8 indexing and reduced tests on types (suggested by P. Kienzle)
%
% Revision 1.3 2004/09/03 17:07:26 jmones
% Support for uint8 and uint16 types added.
%
% Revision 1.2 2004/08/17 15:48:03 jmones
% Clarified expected data for RGB images in doc
%
% Revision 1.1 2004/08/17 15:45:40 jmones
% cmunique: Finds colormap with unique colors and corresponding image
%
%