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