wolffd@0
|
1 function [color,centroids]=som_kmeanscolor2(mode,sM,C,initRGB,contrast,R)
|
wolffd@0
|
2
|
wolffd@0
|
3 % SOM_KMEANSCOLOR2 Color codes a SOM according to averaged or best K-means clustering
|
wolffd@0
|
4 %
|
wolffd@0
|
5 % color = som_kmeanscolor2('average',sM, C, [initRGB], [contrast],[R])
|
wolffd@0
|
6 %
|
wolffd@0
|
7 % color=som_kmeanscolor2('average',sM,[2 4 8 16],som_colorcode(sM,'rgb1'),'enhanced');
|
wolffd@0
|
8 % [color,centroid]=som_kmeanscolor2('best',sM,15,[],'flat',R);
|
wolffd@0
|
9 %
|
wolffd@0
|
10 % Input and output arguments ([]'s are optional):
|
wolffd@0
|
11 %
|
wolffd@0
|
12 % mode (string) 'average' or 'best', defalut: 'average'
|
wolffd@0
|
13 % sM (struct) a map struct
|
wolffd@0
|
14 % C (vector) number of clusters
|
wolffd@0
|
15 % [initRGB] (string, matrix) a color code string accepted by SOM_COLORCODE
|
wolffd@0
|
16 % or an Mx3 matrix of RGB triples, where M is the number
|
wolffd@0
|
17 % of map units. Default: SOM_COLORCODEs default
|
wolffd@0
|
18 % [contrast] (string) 'flat', 'enhanced' color contrast mode, default:
|
wolffd@0
|
19 % 'enhanced'.
|
wolffd@0
|
20 % [R] (scalar) number of K-means trials, default: 30.
|
wolffd@0
|
21 % color (matrix) Mx3xC of RGB triples
|
wolffd@0
|
22 % centroid (array of matrices) centroid{i} includes codebook for the best
|
wolffd@0
|
23 % k-means for C(i) clusters, i.e. the cluster centroids corresponding to
|
wolffd@0
|
24 % the color code color(:,:,i).
|
wolffd@0
|
25 %
|
wolffd@0
|
26 % The function gives a set of color codes for the SOM according to K-means
|
wolffd@0
|
27 % clustering. It has two operation modes:
|
wolffd@0
|
28 %
|
wolffd@0
|
29 % 'average': The idea of coloring is that the color of the units belonging to the same
|
wolffd@0
|
30 % cluster is the mean of the original RGB values (see SOM_COLORCODE) of the map units
|
wolffd@0
|
31 % belonging to the cluster (see SOM_CLUSTERCOLOR). The K-means clustering is made,
|
wolffd@0
|
32 % by default, 30 times and the resulting color codes are averaged for
|
wolffd@0
|
33 % each specified number of clusters C(i), i=1,...,k. In a way, the resulting averaged color
|
wolffd@0
|
34 % codes reflect the stability of the K-means clustering made on the map units.
|
wolffd@0
|
35 %
|
wolffd@0
|
36 % 'best': runs the k-means R times for C(i), i=1,...,n clusters as in previous mode,
|
wolffd@0
|
37 % but instead of averaging all the R color codes, it picks the one that corresponds to the
|
wolffd@0
|
38 % best k-means clustering for each C(i). The 'best' is the one with the lowest
|
wolffd@0
|
39 % quantization error. The result may differ from run to run.
|
wolffd@0
|
40 %
|
wolffd@0
|
41 % EXAMPLE
|
wolffd@0
|
42 %
|
wolffd@0
|
43 % load iris; % or any other map struct sM
|
wolffd@0
|
44 % color=som_kmeanscolor2('average',sM,[2:6]);
|
wolffd@0
|
45 % som_show(sM,'umat','all','color',color);
|
wolffd@0
|
46 %
|
wolffd@0
|
47 % See also SOM_KMEANS, SOM_SHOW, SOM_COLORCODE, SOM_CLUSTERCOLOR, SOM_KMEANSCOLOR
|
wolffd@0
|
48
|
wolffd@0
|
49 % Contributed to SOM Toolbox 2.0, 2001 February by Johan Himberg
|
wolffd@0
|
50 % Copyright (c) by Johan Himberg
|
wolffd@0
|
51 % http://www.cis.hut.fi/projects/somtoolbox/
|
wolffd@0
|
52
|
wolffd@0
|
53 %%% Check number of inputs
|
wolffd@0
|
54
|
wolffd@0
|
55 error(nargchk(3, 6, nargin)); % check no. of input args
|
wolffd@0
|
56
|
wolffd@0
|
57 %%% Check input args & set defaults
|
wolffd@0
|
58
|
wolffd@0
|
59 if ~vis_valuetype(mode,{'string'}),
|
wolffd@0
|
60 error('Mode must be a string.');
|
wolffd@0
|
61 end
|
wolffd@0
|
62 switch lower(mode),
|
wolffd@0
|
63 case{'average','best'}
|
wolffd@0
|
64 ;
|
wolffd@0
|
65 otherwise
|
wolffd@0
|
66 error('Mode must be string ''average'' or ''best''.');
|
wolffd@0
|
67 end
|
wolffd@0
|
68
|
wolffd@0
|
69 if isstruct(sM) & isfield(sM,'type') & strcmp(sM.type,'som_map'),
|
wolffd@0
|
70 [tmp,lattice,msize]=vis_planeGetArgs(sM);
|
wolffd@0
|
71 munits=prod(msize);
|
wolffd@0
|
72 if length(msize)>2
|
wolffd@0
|
73 error('Does not work with 3D maps.')
|
wolffd@0
|
74 end
|
wolffd@0
|
75 else
|
wolffd@0
|
76 error('Map struct required for the second input argument!');
|
wolffd@0
|
77 end
|
wolffd@0
|
78
|
wolffd@0
|
79 if ~vis_valuetype(C,{'1xn','nx1'}),
|
wolffd@0
|
80 error('Vector value expected for cluster number.');
|
wolffd@0
|
81 end
|
wolffd@0
|
82
|
wolffd@0
|
83 % Round C and check
|
wolffd@0
|
84 C=round(C(:)');
|
wolffd@0
|
85
|
wolffd@0
|
86 if any(C<2),
|
wolffd@0
|
87 error('Cluster number must be 2 or more.');
|
wolffd@0
|
88 end
|
wolffd@0
|
89
|
wolffd@0
|
90 % check initial color coding
|
wolffd@0
|
91 if nargin<4 | isempty(initRGB)
|
wolffd@0
|
92 initRGB=som_colorcode(sM);
|
wolffd@0
|
93 end
|
wolffd@0
|
94
|
wolffd@0
|
95 % check contrast checking
|
wolffd@0
|
96 if nargin<5 | isempty(contrast),
|
wolffd@0
|
97 contrast='enhanced';
|
wolffd@0
|
98 end
|
wolffd@0
|
99
|
wolffd@0
|
100 if ~ischar(contrast),
|
wolffd@0
|
101 error('String input expected for input arg. ''contrast''.');
|
wolffd@0
|
102 else
|
wolffd@0
|
103 switch lower(contrast)
|
wolffd@0
|
104 case {'flat','enhanced'}
|
wolffd@0
|
105 ;
|
wolffd@0
|
106 otherwise
|
wolffd@0
|
107 error(['''flat'' or ''enhanced'' expected for '...
|
wolffd@0
|
108 'input argument ''contrast''.']);
|
wolffd@0
|
109 end
|
wolffd@0
|
110 end
|
wolffd@0
|
111
|
wolffd@0
|
112 if ischar(initRGB),
|
wolffd@0
|
113 try
|
wolffd@0
|
114 initRGB=som_colorcode(sM,initRGB);
|
wolffd@0
|
115 catch
|
wolffd@0
|
116 error(['Color code ' initRGB ...
|
wolffd@0
|
117 'was not recognized by SOM_COLORCODE.']);
|
wolffd@0
|
118 end
|
wolffd@0
|
119 elseif vis_valuetype(initRGB,{'nx3rgb',[munits 3]},'all'),
|
wolffd@0
|
120 ;
|
wolffd@0
|
121 else
|
wolffd@0
|
122 error(['The initial color code must be a string '...
|
wolffd@0
|
123 'or an Mx3 matrix of RGB triples.']);
|
wolffd@0
|
124 end
|
wolffd@0
|
125
|
wolffd@0
|
126 if nargin<6|isempty(R),
|
wolffd@0
|
127 R=30;
|
wolffd@0
|
128 end
|
wolffd@0
|
129
|
wolffd@0
|
130 if ~vis_valuetype(R,{'1x1'}),
|
wolffd@0
|
131 error('''R'' must be scalar.');
|
wolffd@0
|
132 end
|
wolffd@0
|
133
|
wolffd@0
|
134 %%% Action %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
135
|
wolffd@0
|
136 disp('Wait...');
|
wolffd@0
|
137 index=0; hit_=zeros(munits,munits);
|
wolffd@0
|
138
|
wolffd@0
|
139 switch mode,
|
wolffd@0
|
140 %% Averaged k-means coloring
|
wolffd@0
|
141 case 'average'
|
wolffd@0
|
142 for k=C,
|
wolffd@0
|
143 disp(['Running K-means for ' num2str(k) ' clusters...']);
|
wolffd@0
|
144 color_=zeros(munits,3);
|
wolffd@0
|
145 colord_=color_;
|
wolffd@0
|
146 % Average R k-means colorings for C clusters
|
wolffd@0
|
147 for j=1:R,
|
wolffd@0
|
148 [dummy,c]=som_kmeans('batch',sM,k,100,0); % max 100 iterations, verbose off
|
wolffd@0
|
149 color_=color_+som_clustercolor(sM,c,initRGB);
|
wolffd@0
|
150 end
|
wolffd@0
|
151 index=index+1;
|
wolffd@0
|
152 color(:,:,index)=color_./R;
|
wolffd@0
|
153 end
|
wolffd@0
|
154
|
wolffd@0
|
155 %% coloring for 'best' k-means coloring
|
wolffd@0
|
156 case 'best'
|
wolffd@0
|
157 for k=C,
|
wolffd@0
|
158 disp(['Running K-means for ' num2str(k) ' clusters...']);
|
wolffd@0
|
159 c=[];err=Inf; div=[];
|
wolffd@0
|
160 %% look for the best k-means among R trials
|
wolffd@0
|
161 for i=1:R,
|
wolffd@0
|
162 [c_,div_,err_(i)]=som_kmeans('batch',sM,k,100,0); % max 100 iterations, verbose off
|
wolffd@0
|
163 if err_(i)<err,
|
wolffd@0
|
164 err=err_(i); c=c_; div=div_;
|
wolffd@0
|
165 end
|
wolffd@0
|
166 end
|
wolffd@0
|
167 % record the 'best' k-means for C clusters
|
wolffd@0
|
168 index=index+1;
|
wolffd@0
|
169 color(:,:,index)=som_clustercolor(sM,div,initRGB);
|
wolffd@0
|
170 centroid{index}=c;
|
wolffd@0
|
171 end
|
wolffd@0
|
172 end
|
wolffd@0
|
173
|
wolffd@0
|
174 %%% Build output
|
wolffd@0
|
175
|
wolffd@0
|
176 switch contrast
|
wolffd@0
|
177 case 'flat'
|
wolffd@0
|
178 ;
|
wolffd@0
|
179 case 'enhanced'
|
wolffd@0
|
180 warning off;
|
wolffd@0
|
181 ncolor=maxnorm(color);
|
wolffd@0
|
182 ncolor(~isfinite(ncolor))=color(~isfinite(ncolor));
|
wolffd@0
|
183 color=ncolor;
|
wolffd@0
|
184 warning on;
|
wolffd@0
|
185 end
|
wolffd@0
|
186
|
wolffd@0
|
187
|
wolffd@0
|
188 %%% Subfunctions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
189 function X=maxnorm(x)
|
wolffd@0
|
190 % normalize columns of x between [0,1]
|
wolffd@0
|
191
|
wolffd@0
|
192 x=x-repmat(min(x),[size(x,1) 1 1]);
|
wolffd@0
|
193 X=x./repmat(max(x),[size(x,1) 1 1]);
|