wolffd@0
|
1 function varargout = mirnovelty(orig,varargin)
|
wolffd@0
|
2 % n = mirnovelty(m) evaluates the novelty score from a similarity matrix.
|
wolffd@0
|
3 % [n,m] = mirnovelty(m) also return the similarity matrix.
|
wolffd@0
|
4 % Optional argument:
|
wolffd@0
|
5 % mirnovelty(...,'Distance',f) specifies the name of a dissimilarity
|
wolffd@0
|
6 % distance function, from those proposed in the Statistics Toolbox
|
wolffd@0
|
7 % (help pdist).
|
wolffd@0
|
8 % default value: f = 'cosine'
|
wolffd@0
|
9 % mirnovelty(...,'Similarity',f) specifies the name of a similarity
|
wolffd@0
|
10 % measure function. This function is applied to the result of the
|
wolffd@0
|
11 % distance function. cf. mirsimatrix
|
wolffd@0
|
12 % default value: f = 'exponential'
|
wolffd@0
|
13 % corresponding to f(x) = exp(-x)
|
wolffd@0
|
14 % mirnovelty(...,'KernelSize',s) or more simply mirnovelty(...,s)
|
wolffd@0
|
15 % specifies the length of the gaussian kernel, in samples.
|
wolffd@0
|
16 % default value: s = 64.
|
wolffd@0
|
17 % mirnovelty(...,'Normal',0) does not normalize the novelty curve
|
wolffd@0
|
18 % between the values 0 and 1.
|
wolffd@0
|
19 %
|
wolffd@0
|
20 % Foote, J. & Cooper, M. (2003). Media Segmentation using Self-Similarity
|
wolffd@0
|
21 % Decomposition,. In Proc. SPIE Storage and Retrieval for Multimedia
|
wolffd@0
|
22 % Databases, Vol. 5021, pp. 167-75.
|
wolffd@0
|
23
|
wolffd@0
|
24 dist.key = 'Distance';
|
wolffd@0
|
25 dist.type = 'String';
|
wolffd@0
|
26 dist.default = 'cosine';
|
wolffd@0
|
27 option.dist = dist;
|
wolffd@0
|
28
|
wolffd@0
|
29 sm.key = {'Measure','Similarity'};
|
wolffd@0
|
30 sm.type = 'String';
|
wolffd@0
|
31 sm.default = 'exponential';
|
wolffd@0
|
32 option.sm = sm;
|
wolffd@0
|
33
|
wolffd@0
|
34 K.key = {'KernelSize','Width'};
|
wolffd@0
|
35 K.type = 'Integer';
|
wolffd@0
|
36 K.default = 64;
|
wolffd@0
|
37 option.K = K;
|
wolffd@0
|
38
|
wolffd@0
|
39 transf.type = 'String';
|
wolffd@0
|
40 transf.default = 'TimeLag';
|
wolffd@0
|
41 transf.choice = {'Horizontal','TimeLag'};
|
wolffd@0
|
42 option.transf = transf;
|
wolffd@0
|
43
|
wolffd@0
|
44 normal.key = 'Normal';
|
wolffd@0
|
45 normal.type = 'Boolean';
|
wolffd@0
|
46 normal.default = 1;
|
wolffd@0
|
47 normal.when = 'After';
|
wolffd@0
|
48 option.normal = normal;
|
wolffd@0
|
49
|
wolffd@0
|
50 specif.option = option;
|
wolffd@0
|
51 specif.combineframes = @combineframes;
|
wolffd@0
|
52 specif.nochunk = 1;
|
wolffd@0
|
53 varargout = mirfunction(@mirnovelty,orig,varargin,nargout,specif,@init,@main);
|
wolffd@0
|
54
|
wolffd@0
|
55
|
wolffd@0
|
56 function [x type] = init(x,option)
|
wolffd@0
|
57 type = 'mirscalar';
|
wolffd@0
|
58 if not(isamir(x,'mirscalar') && strcmp(get(x,'Title'),'Novelty'))
|
wolffd@0
|
59 x = mirsimatrix(x,'Distance',option.dist,'Similarity',option.sm,...
|
wolffd@0
|
60 'Width',option.K,option.transf);
|
wolffd@0
|
61 end
|
wolffd@0
|
62 if isa(x,'mirdesign')
|
wolffd@0
|
63 x = set(x,'Overlap',ceil(option.K));
|
wolffd@0
|
64 end
|
wolffd@0
|
65
|
wolffd@0
|
66
|
wolffd@0
|
67 function y = main(orig,option,postoption)
|
wolffd@0
|
68 if iscell(orig)
|
wolffd@0
|
69 orig = orig{1};
|
wolffd@0
|
70 end
|
wolffd@0
|
71 if not(isa(orig,'mirscalar'))
|
wolffd@0
|
72 s = get(orig,'Data');
|
wolffd@0
|
73 dw = get(orig,'DiagWidth');
|
wolffd@0
|
74 for k = 1:length(s)
|
wolffd@0
|
75 if isnumeric(dw)
|
wolffd@0
|
76 dwk = dw;
|
wolffd@0
|
77 else
|
wolffd@0
|
78 dwk = dw{k};
|
wolffd@0
|
79 end
|
wolffd@0
|
80 if option.K
|
wolffd@0
|
81 cgs = min(option.K,dwk);
|
wolffd@0
|
82 else
|
wolffd@0
|
83 cgs = dwk;
|
wolffd@0
|
84 end
|
wolffd@0
|
85 cg = checkergauss(cgs,option.transf);
|
wolffd@0
|
86 disp('Computing convolution, please wait...')
|
wolffd@0
|
87 for z = 1:length(s{k})
|
wolffd@0
|
88 sz = s{k}{z};
|
wolffd@0
|
89 szm = max(max(sz));
|
wolffd@0
|
90 for i = find(isnan(sz))
|
wolffd@0
|
91 sz(i) = szm;
|
wolffd@0
|
92 end
|
wolffd@0
|
93 cv = convolve2(sz,cg,'same');
|
wolffd@0
|
94 nl = size(cv,1);
|
wolffd@0
|
95 nc = size(cv,2);
|
wolffd@0
|
96 if nl == 0
|
wolffd@0
|
97 warning('WARNING IN NOVELTY: No frame decomposition. The novelty score cannot be computed.');
|
wolffd@0
|
98 score{k}{z} = [];
|
wolffd@0
|
99 else
|
wolffd@0
|
100 sco = cv(floor(size(cv,1)/2),:);
|
wolffd@0
|
101 incr = find(diff(sco)>=0);
|
wolffd@0
|
102 if not(isempty(incr))
|
wolffd@0
|
103 decr = find(diff(sco)<=0);
|
wolffd@0
|
104 sco(1:incr(1)-1) = NaN(1,incr(1)-1);
|
wolffd@0
|
105 if not(isempty(decr))
|
wolffd@0
|
106 sco(decr(end)+1:end) = NaN(1,length(sco)-decr(end));
|
wolffd@0
|
107 end
|
wolffd@0
|
108 incr = find(diff(sco)>=0);
|
wolffd@0
|
109 sco2 = sco;
|
wolffd@0
|
110 if not(isempty(incr))
|
wolffd@0
|
111 sco2 = sco2(1:incr(end)+1);
|
wolffd@0
|
112 end
|
wolffd@0
|
113 decr = find(diff(sco)<=0);
|
wolffd@0
|
114 if not(isempty(decr)) && decr(1)>2
|
wolffd@0
|
115 sco2 = sco2(decr(1)-1:end);
|
wolffd@0
|
116 end
|
wolffd@0
|
117 mins = min(sco2);
|
wolffd@0
|
118 rang = find(sco>= mins);
|
wolffd@0
|
119 if not(isempty(rang))
|
wolffd@0
|
120 sco(1:rang(1)-1) = NaN(1,rang(1)-1);
|
wolffd@0
|
121 sco(rang(end)+1:end) = NaN(1,length(sco)-rang(end));
|
wolffd@0
|
122 end
|
wolffd@0
|
123 end
|
wolffd@0
|
124 score{k}{z} = sco;
|
wolffd@0
|
125 end
|
wolffd@0
|
126 end
|
wolffd@0
|
127 end
|
wolffd@0
|
128 else
|
wolffd@0
|
129 score = get(orig,'Data');
|
wolffd@0
|
130 end
|
wolffd@0
|
131 if not(isempty(postoption)) && postoption.normal
|
wolffd@0
|
132 for k = 1:length(score)
|
wolffd@0
|
133 for l = 1:length(score{k})
|
wolffd@0
|
134 sco = score{k}{l};
|
wolffd@0
|
135 sco = (sco-min(sco))/(max(sco)-min(sco));
|
wolffd@0
|
136 score{k}{l} = sco;
|
wolffd@0
|
137 end
|
wolffd@0
|
138 end
|
wolffd@0
|
139 end
|
wolffd@0
|
140 n = mirscalar(orig,'Data',score,'Title','Novelty');
|
wolffd@0
|
141 y = {n orig};
|
wolffd@0
|
142
|
wolffd@0
|
143
|
wolffd@0
|
144 function old = combineframes(old,new)
|
wolffd@0
|
145 if not(iscell(old))
|
wolffd@0
|
146 old = {old};
|
wolffd@0
|
147 end
|
wolffd@0
|
148 if not(iscell(new))
|
wolffd@0
|
149 new = {new};
|
wolffd@0
|
150 end
|
wolffd@0
|
151 for var = 1:length(new)
|
wolffd@0
|
152 ov = old{var};
|
wolffd@0
|
153 nv = new{var};
|
wolffd@0
|
154 ofp = get(ov,'FramePos');
|
wolffd@0
|
155 ofp = ofp{1}{1};
|
wolffd@0
|
156 nfp = get(nv,'FramePos');
|
wolffd@0
|
157 nfp = nfp{1}{1};
|
wolffd@0
|
158 od = get(ov,'Data');
|
wolffd@0
|
159 od = od{1}{1};
|
wolffd@0
|
160 onan = find(isnan(od));
|
wolffd@0
|
161 od(onan) = [];
|
wolffd@0
|
162 ofp(:,onan) = [];
|
wolffd@0
|
163 nd = get(nv,'Data');
|
wolffd@0
|
164 nd = nd{1}{1};
|
wolffd@0
|
165 nnan = find(isnan(nd));
|
wolffd@0
|
166 nd(nnan) = [];
|
wolffd@0
|
167 nfp(:,nnan) = [];
|
wolffd@0
|
168 [unused omatch nmatch] = intersect(ofp(1,:),nfp(1,:));
|
wolffd@0
|
169 if isempty(omatch)
|
wolffd@0
|
170 ov = set(ov,'FramePos',{{[ofp nfp]}},'Data',{{[od nd]}});
|
wolffd@0
|
171 else
|
wolffd@0
|
172 lm = length(omatch);
|
wolffd@0
|
173 ov = set(ov,'FramePos',{{[ofp(:,1:omatch(1)-1) nfp]}},...
|
wolffd@0
|
174 'Data',{{[od(1:omatch(1)-1),...
|
wolffd@0
|
175 (od(omatch).*(lm:-1:1) + nd(nmatch).*(1:lm))/(lm+1),...
|
wolffd@0
|
176 nd(nmatch(end)+1:end)]}});
|
wolffd@0
|
177 end
|
wolffd@0
|
178 old{var} = ov;
|
wolffd@0
|
179 end
|
wolffd@0
|
180
|
wolffd@0
|
181
|
wolffd@0
|
182 function y = checkergauss(N,transf)
|
wolffd@0
|
183 hN = ceil(N/2);
|
wolffd@0
|
184 if strcmpi(transf,'TimeLag')
|
wolffd@0
|
185 y = zeros(hN,N);
|
wolffd@0
|
186 for j = 1:N
|
wolffd@0
|
187 for i = 1:hN
|
wolffd@0
|
188 g = exp(-((i/hN)^2 + (((j-hN)/hN)^2))*4);
|
wolffd@0
|
189 if j>hN && j<hN+i
|
wolffd@0
|
190 y(hN-i+1,j) = -g;
|
wolffd@0
|
191 else
|
wolffd@0
|
192 y(hN-i+1,j) = g;
|
wolffd@0
|
193 end
|
wolffd@0
|
194 end
|
wolffd@0
|
195 end
|
wolffd@0
|
196 else
|
wolffd@0
|
197 y = zeros(N);
|
wolffd@0
|
198 for i = 1:N
|
wolffd@0
|
199 for j = 1:N
|
wolffd@0
|
200 g = exp(-(((i-hN)/hN)^2 + (((j-hN)/hN)^2))*4);
|
wolffd@0
|
201 if xor(j>i,j>N-i)
|
wolffd@0
|
202 y(i,j) = -g;
|
wolffd@0
|
203 else
|
wolffd@0
|
204 y(i,j) = g;
|
wolffd@0
|
205 end
|
wolffd@0
|
206 end
|
wolffd@0
|
207 end
|
wolffd@0
|
208 end |