diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toolboxes/MIRtoolbox1.3.2/MIRToolbox/@mirsimatrix/mirsimatrix.m	Tue Feb 10 15:05:51 2015 +0000
@@ -0,0 +1,414 @@
+function varargout = mirsimatrix(orig,varargin)
+%   m = mirsimatrix(x) computes the similarity matrix resulting from the 
+%       mutual comparison between each possible frame analysis in x.
+%           By default, x is the spectrum of the frame decomposition.
+%           But it can be any other frame analysis.
+%   Optional argument:
+%       mirsimatrix(...,'Distance',f) specifies the name of a distance
+%           function, from those proposed in the Statistics Toolbox
+%               (help pdist).
+%           default value: f = 'cosine'
+%       mirsimatrix(...,'Dissimilarity') return the dissimilarity matrix,
+%           which is the intermediary result before the computation of the 
+%           actual similarity matrix. It shows the distance between each
+%           possible frame analysis in x.
+%       mirsimatrix(...,'Similarity',f) indicates the function f specifying
+%           the way the distance values in the dissimilarity matrix are
+%           transformed into similarity values.
+%           Possible values:
+%               f = 'oneminus' (default value) 
+%                   corresponding to f(x) = 1-x
+%               f = 'exponential'
+%                   corresponding to f(x)= exp(-x)
+%       mirsimatrix(...,'Width',w) or more simply dissimatrix(...,w) 
+%           specifies the size of the diagonal bandwidth, in samples,
+%           outside which the dissimilarity will not be computed.
+%           if w = inf (default value), all the matrix will be computed.
+%       mirsimatrix(...,'Horizontal') rotates the matrix 45 degrees in order to
+%           make the first diagonal horizontal, and to restrict on the
+%           diagonal bandwidth only.
+%       mirsimatrix(...,'TimeLag') transforms the (non-rotated) matrix into
+%           a time-lag matrix, making the first diagonal horizontal as well
+%           (corresponding to the zero-lag line).
+%
+%       mirsimatrix(M,r) creates a mirsimatrix similarity matrix based on
+%           the Matlab square matrix M, of frame rate r (in Hz.)
+%               By default r = 20 Hz.
+%           mirsimatrix(M,r,'Dissimilarity') creates instead a mirsimatrix
+%               dissimilarity matrix.
+%
+%   Foote, J. & Cooper, M. (2003). Media Segmentation using Self-Similarity
+% Decomposition,. In Proc. SPIE Storage and Retrieval for Multimedia
+% Databases, Vol. 5021, pp. 167-75.
+
+%       mirsimatrix(...,'Filter',10) filter along the diagonal of the matrix,
+%           using a uniform moving average filter of size f. The result is
+%           represented in a time-lag matrix.
+
+
+        distance.key = 'Distance';
+        distance.type = 'String';
+        distance.default = 'cosine';
+    option.distance = distance;
+
+        simf.key = 'Similarity';
+        simf.type = 'String';
+        simf.default = 'oneminus';
+        simf.keydefault = 'Similarity';        
+        simf.when = 'After';
+    option.simf = simf;
+
+        dissim.key = 'Dissimilarity';
+        dissim.type = 'Boolean';
+        dissim.default = 0;
+    option.dissim = dissim;
+    
+        K.key = 'Width';
+        K.type = 'Integer';
+        K.default = Inf;
+    option.K = K;
+    
+        filt.key = 'Filter';
+        filt.type = 'Integer';
+        filt.default = 0;
+        filt.when = 'After';
+    option.filt = filt;
+
+        view.type = 'String';
+        view.default = 'Standard';
+        view.choice = {'Standard','Horizontal','TimeLag'};
+        view.when = 'After';
+    option.view = view;
+    
+        rate.type = 'Integer';
+        rate.position = 2;
+        rate.default = 20;
+    option.rate = rate;
+    
+specif.option = option;
+specif.nochunk = 1;
+varargout = mirfunction(@mirsimatrix,orig,varargin,nargout,specif,@init,@main);
+
+
+function [x type] = init(x,option)
+if isnumeric(x)
+    m.diagwidth = Inf;
+    m.view = 's';
+    m.similarity = NaN;
+    m.graph = {};
+    m.branch = {};
+    m = class(m,'mirsimatrix',mirdata);
+    m = set(m,'Title','Dissimilarity matrix');
+    fp = repmat(((1:size(x,1))-.5)/option.rate,[2,1]);
+    x = set(m,'Data',{x},'Pos',[],...
+              'FramePos',{{fp}},'Name',{inputname(1)});
+else
+    if not(isamir(x,'mirsimatrix'))
+        if (isamir(x,'miraudio'))
+            if isframed(x)
+                x = mirspectrum(x);
+            else
+                x = mirspectrum(x,'Frame',0.05,1);
+            end
+        end
+    end
+end
+type = 'mirsimatrix';
+
+
+function m = main(orig,option,postoption)
+if iscell(orig)
+    orig = orig{1};
+end
+if isa(orig,'mirsimatrix')
+    d = get(orig,'Data');
+    for k = 1:length(d)
+        if iscell(option) && isfield(option,'K') && option.K < orig.diagwidth
+            nl = size(d{k},1);
+            if strcmp(orig.view,'h')
+                dl = (nl - option.K)/2;
+                dk = d{k}(ceil(dl):nl-floor(dl),:);
+            else
+                [spA,spd] = spdiags(d{k},-ceil(option.K/2):ceil(option.K/2));
+                dk = full(spdiags(spA,spd,nl,size(d{k},2)));
+            end
+            d{k} = dk;
+            orig.diagwidth = option.K;
+        end
+    end
+    m = set(orig,'Data',d);
+else
+    v = get(orig,'Data');
+    d = cell(1,length(v));
+    for k = 1:length(v)
+        vk = v{k};
+        if mirwaitbar
+            handle = waitbar(0,'Computing dissimilarity matrix...');
+        else
+            handle = 0;
+        end
+        if 0 %iscell(vk)
+            try
+                vk = cell2mat(vk);
+            end
+        end
+        if 0 %iscell(vk) %&& length(vk) > 1 %%% ATTENTION KL!!<<<<<<<<<<<<
+            l = length(vk);
+            dk = NaN(l,l);
+            hK = floor(option.K/2);
+            for i = 1:l
+                if handle
+                    waitbar(i/l,handle);
+                end
+                for j = max(1,i-hK):min(l,i+hK)
+                    dk(i,j) = KL(vk{i},vk{j});
+                end
+            end
+        else
+            if not(iscell(vk))
+                vk = {vk};
+            end    
+            for z = 1:length(vk)
+                vz = vk{z};
+                ll = size(vz,1);
+                l = size(vz,2);
+                nc = size(vz,3);
+                if ll==1 && nc>1
+                    vz = squeeze(vz)';
+                    ll = nc;
+                    nc = 1;
+                end
+                nd = size(vz,4);
+                if not(isempty(postoption)) && ...
+                    strcmpi(postoption.view,'TimeLag')
+                    lK = ceil(option.K/2);
+                    if isinf(lK)
+                        lK = l;
+                    end
+                    dk{z} = NaN(lK,l,nc);
+                else
+                    dk{z} = NaN(l,l,nc);
+                end
+                for g = 1:nc
+                    if nd == 1
+                        vv = vz;
+                    else
+                        vv = zeros(ll*nd,l);
+                        for h = 1:nd
+                            if iscell(vz)
+                                for i = 1:ll
+                                    for j = 1:l
+                                        vj = vz{i,j,g,h};
+                                        if isempty(vj)
+                                            vv((h-1)*ll+i,j) = NaN;
+                                        else
+                                            vv((h-1)*ll+i,j) = vj;
+                                        end
+                                    end
+                                end
+                            else
+                                tic
+                                vv((h-1)*ll+1:h*ll,:) = vz(:,:,g,h);
+                                toc
+                            end
+                        end
+                    end
+                    if isinf(option.K) && not(strcmpi(postoption.view,'TimeLag'))
+                        try
+                            manually = 0;
+                            dk{z}(:,:,g) = squareform(pdist(vv',option.distance));
+                            if option.K < Inf
+                                [spA,spd] = spdiags(dk{z},...
+                                    -ceil(option.K/2):ceil(option.K/2));
+                                dk{z}(:,:,g) = full(spdiags(spA,spd,size(dk,1),size(dk{z},2)));
+                            end
+                        catch
+                            %err = lasterror;
+                            %warning(err.message)
+                            %disp('Statistics Toolbox does not seem to be
+                            %installed. Recompute the distance matrix manually.');
+                            manually = 1;
+                        end
+                    else
+                        manually = 1;
+                    end
+                    if manually
+                        disf = str2func(option.distance);
+                        if strcmpi(option.distance,'cosine')
+                            for i = 1:l
+                                vv(:,i) = vv(:,i)/norm(vv(:,i));
+                            end
+                        end
+                        if not(isempty(postoption)) && ...
+                                strcmpi(postoption.view,'TimeLag')
+                            lK = ceil(option.K/2);
+                            for i = 1:l
+                                if mirwaitbar && (mod(i,100) == 1 || i == l)
+                                    waitbar(i/l,handle);
+                                end
+                                ij = min(i+lK-1,l);
+                                dkij = disf(vv(:,i),vv(:,i:ij));
+                                for j = 1:ij-i+1
+                                    dk{z}(j,i+j-1,g) = dkij(j);
+                                end
+                            end
+                        else
+                            for i = 1:l
+                                if mirwaitbar && (mod(i,100) == 1 || i == l)
+                                    waitbar(i/l,handle);
+                                end
+                                j = min(i+option.K-1,l);
+                                dkij = disf(vv(:,i),vv(:,i:j));
+                                dk{z}(i,i:j,g) = dkij;
+                                dk{z}(i:j,i,g) = dkij';
+                            end
+                        end
+                    end
+                end
+            end
+        end
+        d{k} = dk;
+        if handle
+            delete(handle)
+        end
+    end
+    m.diagwidth = option.K;
+    if not(isempty(postoption)) && strcmpi(postoption.view,'TimeLag')
+        m.view = 'l';
+    else
+        m.view = 's';
+    end
+    m.similarity = 0;
+    m.graph = {};
+    m.branch = {};
+    m = class(m,'mirsimatrix',mirdata(orig));
+    m = purgedata(m);
+    m = set(m,'Title','Dissimilarity matrix');
+    m = set(m,'Data',d,'Pos',[]);
+end
+if not(isempty(postoption))
+    if strcmpi(m.view,'s')
+        if strcmpi(postoption.view,'Horizontal')
+            for k = 1:length(d)
+                for z = 1:length(d{k})
+                    d{k}{z} = rotatesim(d{k}{z},m.diagwidth);
+                    if option.K < m.diagwidth
+                        W = size(d{k}{z},1);
+                        hW = ceil(W/2);
+                        hK = ceil(option.K/2);
+                        d{k}{z} = d{k}{z}(hW-hK:hW+hK,:);
+                        m.diagwidth = option.K;
+                    end
+                end
+            end
+            m = set(m,'Data',d);
+            m.view = 'h';
+        elseif strcmpi(postoption.view,'TimeLag') || postoption.filt
+            W = ceil(m.diagwidth/2);
+            for k = 1:length(d)
+                for z = 1:length(d{k})
+                    if isinf(W)
+                        dz = NaN(size(d{k}{z}));
+                    else
+                        dz = NaN(W,size(d{k}{z},2));
+                    end
+                    for l = 1:size(dz,1)
+                        dz(l,l:end) = diag(d{k}{z},l-1)';
+                    end
+                    if option.K < m.diagwidth
+                        dz = dz(1:ceil(option.K/2),:);
+                        m.diagwidth = option.K;
+                    end
+                    d{k}{z}= dz;
+                end
+            end
+            m = set(m,'Data',d);
+            m.view = 'l';
+        end
+    end
+    if ischar(postoption.simf)
+        if strcmpi(postoption.simf,'Similarity')
+            if not(isequal(m.similarity,NaN))
+                option.dissim = 0;
+            end
+            postoption.simf = 'oneminus';
+        end
+        if isequal(m.similarity,0) && isstruct(option) ...
+                && isfield(option,'dissim') && not(option.dissim)
+            simf = str2func(postoption.simf);
+            for k = 1:length(d)
+                for z = 1:length(d{k})
+                     d{k}{z} = simf(d{k}{z});
+                end
+            end
+            m.similarity = postoption.simf;
+            m = set(m,'Title','Similarity matrix','Data',d);
+        elseif length(m.similarity) == 1 && isnan(m.similarity) ...
+                && option.dissim
+            m.similarity = 0;
+        end
+    end
+    if postoption.filt
+        fp = get(m,'FramePos');
+        for k = 1:length(d)
+            for z = 1:length(d{k})
+                dz = filter(ones(postoption.filt,1),1,d{k}{z});
+                d{k}{z} = dz(postoption.filt:end,1:end-postoption.filt+1);
+                fp{k}{z} = [fp{k}{z}(1,1:end-postoption.filt+1);...
+                            fp{k}{z}(1,postoption.filt:end)];
+            end
+        end
+        m = set(m,'Data',d,'FramePos',fp);
+    end
+end
+
+
+function S = rotatesim(d,K)
+if length(d) == 1;
+    S = d;
+else
+    K = min(K,size(d,1)*2);
+    lK = floor(K/2);
+    S = NaN(K,size(d,2),size(d,3));
+    for k = 1:size(d,3)
+        for j = -lK:lK
+            S(lK+1+j,:,k) = [NaN(1,floor(abs(j)/2)) diag(d(:,:,k),j)' ...
+                                                    NaN(1,ceil(abs(j)/2))];
+        end
+    end
+end
+
+function d = cosine(r,s)
+d = 1-r'*s;
+%nr = sqrt(r'*r);
+%ns = sqrt(s'*s);
+%if or(nr == 0, ns == 0);
+%    d = 1;
+%else
+%    d = 1 - r'*s/nr/ns;
+%end
+
+
+function d = KL(x,y)
+% Kullback-Leibler distance
+if size(x,4)>1
+    x(end+1:2*end,:,:,1) = x(:,:,:,2);
+    x(:,:,:,2) = [];
+end
+if size(y,4)>1
+    y(end+1:2*end,:,:,1) = y(:,:,:,2);
+    y(:,:,:,2) = [];
+end
+m1 = mean(x);
+m2 = mean(y);
+S1 = cov(x);
+S2 = cov(y);
+d = (trace(S1/S2)+trace(S2/S1)+(m1-m2)'*inv(S1+S2)*(m1-m2))/2 - size(S1,1);
+    
+
+function s = exponential(d)
+    s = exp(-d);
+    
+    
+function s = oneminus(d)
+    s = 1-d;
\ No newline at end of file