comparison toolboxes/MIRtoolbox1.3.2/MIRToolbox/@mirsimatrix/mirsimatrix.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:e9a9cd732c1e
1 function varargout = mirsimatrix(orig,varargin)
2 % m = mirsimatrix(x) computes the similarity matrix resulting from the
3 % mutual comparison between each possible frame analysis in x.
4 % By default, x is the spectrum of the frame decomposition.
5 % But it can be any other frame analysis.
6 % Optional argument:
7 % mirsimatrix(...,'Distance',f) specifies the name of a distance
8 % function, from those proposed in the Statistics Toolbox
9 % (help pdist).
10 % default value: f = 'cosine'
11 % mirsimatrix(...,'Dissimilarity') return the dissimilarity matrix,
12 % which is the intermediary result before the computation of the
13 % actual similarity matrix. It shows the distance between each
14 % possible frame analysis in x.
15 % mirsimatrix(...,'Similarity',f) indicates the function f specifying
16 % the way the distance values in the dissimilarity matrix are
17 % transformed into similarity values.
18 % Possible values:
19 % f = 'oneminus' (default value)
20 % corresponding to f(x) = 1-x
21 % f = 'exponential'
22 % corresponding to f(x)= exp(-x)
23 % mirsimatrix(...,'Width',w) or more simply dissimatrix(...,w)
24 % specifies the size of the diagonal bandwidth, in samples,
25 % outside which the dissimilarity will not be computed.
26 % if w = inf (default value), all the matrix will be computed.
27 % mirsimatrix(...,'Horizontal') rotates the matrix 45 degrees in order to
28 % make the first diagonal horizontal, and to restrict on the
29 % diagonal bandwidth only.
30 % mirsimatrix(...,'TimeLag') transforms the (non-rotated) matrix into
31 % a time-lag matrix, making the first diagonal horizontal as well
32 % (corresponding to the zero-lag line).
33 %
34 % mirsimatrix(M,r) creates a mirsimatrix similarity matrix based on
35 % the Matlab square matrix M, of frame rate r (in Hz.)
36 % By default r = 20 Hz.
37 % mirsimatrix(M,r,'Dissimilarity') creates instead a mirsimatrix
38 % dissimilarity matrix.
39 %
40 % Foote, J. & Cooper, M. (2003). Media Segmentation using Self-Similarity
41 % Decomposition,. In Proc. SPIE Storage and Retrieval for Multimedia
42 % Databases, Vol. 5021, pp. 167-75.
43
44 % mirsimatrix(...,'Filter',10) filter along the diagonal of the matrix,
45 % using a uniform moving average filter of size f. The result is
46 % represented in a time-lag matrix.
47
48
49 distance.key = 'Distance';
50 distance.type = 'String';
51 distance.default = 'cosine';
52 option.distance = distance;
53
54 simf.key = 'Similarity';
55 simf.type = 'String';
56 simf.default = 'oneminus';
57 simf.keydefault = 'Similarity';
58 simf.when = 'After';
59 option.simf = simf;
60
61 dissim.key = 'Dissimilarity';
62 dissim.type = 'Boolean';
63 dissim.default = 0;
64 option.dissim = dissim;
65
66 K.key = 'Width';
67 K.type = 'Integer';
68 K.default = Inf;
69 option.K = K;
70
71 filt.key = 'Filter';
72 filt.type = 'Integer';
73 filt.default = 0;
74 filt.when = 'After';
75 option.filt = filt;
76
77 view.type = 'String';
78 view.default = 'Standard';
79 view.choice = {'Standard','Horizontal','TimeLag'};
80 view.when = 'After';
81 option.view = view;
82
83 rate.type = 'Integer';
84 rate.position = 2;
85 rate.default = 20;
86 option.rate = rate;
87
88 specif.option = option;
89 specif.nochunk = 1;
90 varargout = mirfunction(@mirsimatrix,orig,varargin,nargout,specif,@init,@main);
91
92
93 function [x type] = init(x,option)
94 if isnumeric(x)
95 m.diagwidth = Inf;
96 m.view = 's';
97 m.similarity = NaN;
98 m.graph = {};
99 m.branch = {};
100 m = class(m,'mirsimatrix',mirdata);
101 m = set(m,'Title','Dissimilarity matrix');
102 fp = repmat(((1:size(x,1))-.5)/option.rate,[2,1]);
103 x = set(m,'Data',{x},'Pos',[],...
104 'FramePos',{{fp}},'Name',{inputname(1)});
105 else
106 if not(isamir(x,'mirsimatrix'))
107 if (isamir(x,'miraudio'))
108 if isframed(x)
109 x = mirspectrum(x);
110 else
111 x = mirspectrum(x,'Frame',0.05,1);
112 end
113 end
114 end
115 end
116 type = 'mirsimatrix';
117
118
119 function m = main(orig,option,postoption)
120 if iscell(orig)
121 orig = orig{1};
122 end
123 if isa(orig,'mirsimatrix')
124 d = get(orig,'Data');
125 for k = 1:length(d)
126 if iscell(option) && isfield(option,'K') && option.K < orig.diagwidth
127 nl = size(d{k},1);
128 if strcmp(orig.view,'h')
129 dl = (nl - option.K)/2;
130 dk = d{k}(ceil(dl):nl-floor(dl),:);
131 else
132 [spA,spd] = spdiags(d{k},-ceil(option.K/2):ceil(option.K/2));
133 dk = full(spdiags(spA,spd,nl,size(d{k},2)));
134 end
135 d{k} = dk;
136 orig.diagwidth = option.K;
137 end
138 end
139 m = set(orig,'Data',d);
140 else
141 v = get(orig,'Data');
142 d = cell(1,length(v));
143 for k = 1:length(v)
144 vk = v{k};
145 if mirwaitbar
146 handle = waitbar(0,'Computing dissimilarity matrix...');
147 else
148 handle = 0;
149 end
150 if 0 %iscell(vk)
151 try
152 vk = cell2mat(vk);
153 end
154 end
155 if 0 %iscell(vk) %&& length(vk) > 1 %%% ATTENTION KL!!<<<<<<<<<<<<
156 l = length(vk);
157 dk = NaN(l,l);
158 hK = floor(option.K/2);
159 for i = 1:l
160 if handle
161 waitbar(i/l,handle);
162 end
163 for j = max(1,i-hK):min(l,i+hK)
164 dk(i,j) = KL(vk{i},vk{j});
165 end
166 end
167 else
168 if not(iscell(vk))
169 vk = {vk};
170 end
171 for z = 1:length(vk)
172 vz = vk{z};
173 ll = size(vz,1);
174 l = size(vz,2);
175 nc = size(vz,3);
176 if ll==1 && nc>1
177 vz = squeeze(vz)';
178 ll = nc;
179 nc = 1;
180 end
181 nd = size(vz,4);
182 if not(isempty(postoption)) && ...
183 strcmpi(postoption.view,'TimeLag')
184 lK = ceil(option.K/2);
185 if isinf(lK)
186 lK = l;
187 end
188 dk{z} = NaN(lK,l,nc);
189 else
190 dk{z} = NaN(l,l,nc);
191 end
192 for g = 1:nc
193 if nd == 1
194 vv = vz;
195 else
196 vv = zeros(ll*nd,l);
197 for h = 1:nd
198 if iscell(vz)
199 for i = 1:ll
200 for j = 1:l
201 vj = vz{i,j,g,h};
202 if isempty(vj)
203 vv((h-1)*ll+i,j) = NaN;
204 else
205 vv((h-1)*ll+i,j) = vj;
206 end
207 end
208 end
209 else
210 tic
211 vv((h-1)*ll+1:h*ll,:) = vz(:,:,g,h);
212 toc
213 end
214 end
215 end
216 if isinf(option.K) && not(strcmpi(postoption.view,'TimeLag'))
217 try
218 manually = 0;
219 dk{z}(:,:,g) = squareform(pdist(vv',option.distance));
220 if option.K < Inf
221 [spA,spd] = spdiags(dk{z},...
222 -ceil(option.K/2):ceil(option.K/2));
223 dk{z}(:,:,g) = full(spdiags(spA,spd,size(dk,1),size(dk{z},2)));
224 end
225 catch
226 %err = lasterror;
227 %warning(err.message)
228 %disp('Statistics Toolbox does not seem to be
229 %installed. Recompute the distance matrix manually.');
230 manually = 1;
231 end
232 else
233 manually = 1;
234 end
235 if manually
236 disf = str2func(option.distance);
237 if strcmpi(option.distance,'cosine')
238 for i = 1:l
239 vv(:,i) = vv(:,i)/norm(vv(:,i));
240 end
241 end
242 if not(isempty(postoption)) && ...
243 strcmpi(postoption.view,'TimeLag')
244 lK = ceil(option.K/2);
245 for i = 1:l
246 if mirwaitbar && (mod(i,100) == 1 || i == l)
247 waitbar(i/l,handle);
248 end
249 ij = min(i+lK-1,l);
250 dkij = disf(vv(:,i),vv(:,i:ij));
251 for j = 1:ij-i+1
252 dk{z}(j,i+j-1,g) = dkij(j);
253 end
254 end
255 else
256 for i = 1:l
257 if mirwaitbar && (mod(i,100) == 1 || i == l)
258 waitbar(i/l,handle);
259 end
260 j = min(i+option.K-1,l);
261 dkij = disf(vv(:,i),vv(:,i:j));
262 dk{z}(i,i:j,g) = dkij;
263 dk{z}(i:j,i,g) = dkij';
264 end
265 end
266 end
267 end
268 end
269 end
270 d{k} = dk;
271 if handle
272 delete(handle)
273 end
274 end
275 m.diagwidth = option.K;
276 if not(isempty(postoption)) && strcmpi(postoption.view,'TimeLag')
277 m.view = 'l';
278 else
279 m.view = 's';
280 end
281 m.similarity = 0;
282 m.graph = {};
283 m.branch = {};
284 m = class(m,'mirsimatrix',mirdata(orig));
285 m = purgedata(m);
286 m = set(m,'Title','Dissimilarity matrix');
287 m = set(m,'Data',d,'Pos',[]);
288 end
289 if not(isempty(postoption))
290 if strcmpi(m.view,'s')
291 if strcmpi(postoption.view,'Horizontal')
292 for k = 1:length(d)
293 for z = 1:length(d{k})
294 d{k}{z} = rotatesim(d{k}{z},m.diagwidth);
295 if option.K < m.diagwidth
296 W = size(d{k}{z},1);
297 hW = ceil(W/2);
298 hK = ceil(option.K/2);
299 d{k}{z} = d{k}{z}(hW-hK:hW+hK,:);
300 m.diagwidth = option.K;
301 end
302 end
303 end
304 m = set(m,'Data',d);
305 m.view = 'h';
306 elseif strcmpi(postoption.view,'TimeLag') || postoption.filt
307 W = ceil(m.diagwidth/2);
308 for k = 1:length(d)
309 for z = 1:length(d{k})
310 if isinf(W)
311 dz = NaN(size(d{k}{z}));
312 else
313 dz = NaN(W,size(d{k}{z},2));
314 end
315 for l = 1:size(dz,1)
316 dz(l,l:end) = diag(d{k}{z},l-1)';
317 end
318 if option.K < m.diagwidth
319 dz = dz(1:ceil(option.K/2),:);
320 m.diagwidth = option.K;
321 end
322 d{k}{z}= dz;
323 end
324 end
325 m = set(m,'Data',d);
326 m.view = 'l';
327 end
328 end
329 if ischar(postoption.simf)
330 if strcmpi(postoption.simf,'Similarity')
331 if not(isequal(m.similarity,NaN))
332 option.dissim = 0;
333 end
334 postoption.simf = 'oneminus';
335 end
336 if isequal(m.similarity,0) && isstruct(option) ...
337 && isfield(option,'dissim') && not(option.dissim)
338 simf = str2func(postoption.simf);
339 for k = 1:length(d)
340 for z = 1:length(d{k})
341 d{k}{z} = simf(d{k}{z});
342 end
343 end
344 m.similarity = postoption.simf;
345 m = set(m,'Title','Similarity matrix','Data',d);
346 elseif length(m.similarity) == 1 && isnan(m.similarity) ...
347 && option.dissim
348 m.similarity = 0;
349 end
350 end
351 if postoption.filt
352 fp = get(m,'FramePos');
353 for k = 1:length(d)
354 for z = 1:length(d{k})
355 dz = filter(ones(postoption.filt,1),1,d{k}{z});
356 d{k}{z} = dz(postoption.filt:end,1:end-postoption.filt+1);
357 fp{k}{z} = [fp{k}{z}(1,1:end-postoption.filt+1);...
358 fp{k}{z}(1,postoption.filt:end)];
359 end
360 end
361 m = set(m,'Data',d,'FramePos',fp);
362 end
363 end
364
365
366 function S = rotatesim(d,K)
367 if length(d) == 1;
368 S = d;
369 else
370 K = min(K,size(d,1)*2);
371 lK = floor(K/2);
372 S = NaN(K,size(d,2),size(d,3));
373 for k = 1:size(d,3)
374 for j = -lK:lK
375 S(lK+1+j,:,k) = [NaN(1,floor(abs(j)/2)) diag(d(:,:,k),j)' ...
376 NaN(1,ceil(abs(j)/2))];
377 end
378 end
379 end
380
381 function d = cosine(r,s)
382 d = 1-r'*s;
383 %nr = sqrt(r'*r);
384 %ns = sqrt(s'*s);
385 %if or(nr == 0, ns == 0);
386 % d = 1;
387 %else
388 % d = 1 - r'*s/nr/ns;
389 %end
390
391
392 function d = KL(x,y)
393 % Kullback-Leibler distance
394 if size(x,4)>1
395 x(end+1:2*end,:,:,1) = x(:,:,:,2);
396 x(:,:,:,2) = [];
397 end
398 if size(y,4)>1
399 y(end+1:2*end,:,:,1) = y(:,:,:,2);
400 y(:,:,:,2) = [];
401 end
402 m1 = mean(x);
403 m2 = mean(y);
404 S1 = cov(x);
405 S2 = cov(y);
406 d = (trace(S1/S2)+trace(S2/S1)+(m1-m2)'*inv(S1+S2)*(m1-m2))/2 - size(S1,1);
407
408
409 function s = exponential(d)
410 s = exp(-d);
411
412
413 function s = oneminus(d)
414 s = 1-d;