Mercurial > hg > camir-aes2014
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; |
