wolffd@0
|
1 % ---
|
wolffd@0
|
2 % The DistMeasureMahal class states a wrapper for
|
wolffd@0
|
3 % special Mahalanobis similarity distance, and is compatible with the
|
wolffd@0
|
4 % DistMeasure class
|
wolffd@0
|
5 % ---
|
wolffd@0
|
6 classdef DistMeasureMahal < handle
|
wolffd@0
|
7
|
wolffd@0
|
8 properties (SetAccess = private)
|
wolffd@0
|
9
|
wolffd@0
|
10 mahalW;
|
wolffd@0
|
11
|
wolffd@0
|
12 featX;
|
wolffd@0
|
13
|
wolffd@0
|
14 ids;
|
wolffd@0
|
15 ret_ids;
|
wolffd@0
|
16
|
wolffd@0
|
17 % special delta parameters
|
wolffd@0
|
18 deltafun;
|
wolffd@0
|
19 deltafun_params;
|
wolffd@0
|
20 end
|
wolffd@0
|
21
|
wolffd@0
|
22 methods
|
wolffd@0
|
23
|
wolffd@0
|
24 % ---
|
wolffd@0
|
25 % constructor
|
wolffd@0
|
26 % ---
|
wolffd@0
|
27 function m = DistMeasureMahal(clips, mahalW, featX, deltafun, deltafun_params)
|
wolffd@0
|
28
|
wolffd@0
|
29 if nargin < 4 && (size(featX, 2) ~= numel(clips) || size(featX, 1) ~= length(mahalW))
|
wolffd@0
|
30 error 'wrong input format'
|
wolffd@0
|
31 end
|
wolffd@0
|
32
|
wolffd@0
|
33 % fill index and generate matrix;
|
wolffd@0
|
34 m.ids = [clips.id];
|
wolffd@0
|
35
|
wolffd@0
|
36 % reverse index
|
wolffd@0
|
37 m.ret_ids = sparse(numel(m.ids),1);
|
wolffd@0
|
38 m.ret_ids(m.ids) = 1:numel(m.ids);
|
wolffd@0
|
39
|
wolffd@0
|
40 % ---
|
wolffd@0
|
41 % save mahal Matrix and lazy-copy features
|
wolffd@0
|
42 % ---
|
wolffd@0
|
43 if size(mahalW, 1) ~= size(mahalW, 2)
|
wolffd@0
|
44
|
wolffd@0
|
45 m.mahalW = diag(mahalW);
|
wolffd@0
|
46 else
|
wolffd@0
|
47
|
wolffd@0
|
48 m.mahalW = mahalW;
|
wolffd@0
|
49 end
|
wolffd@0
|
50
|
wolffd@0
|
51 m.featX = featX;
|
wolffd@0
|
52
|
wolffd@0
|
53 % ---
|
wolffd@0
|
54 % special deltas
|
wolffd@0
|
55 % ---
|
wolffd@0
|
56 if nargin > 3
|
wolffd@0
|
57 m.deltafun = deltafun;
|
wolffd@0
|
58 m.deltafun_params = deltafun_params;
|
wolffd@0
|
59 else
|
wolffd@0
|
60 m.deltafun = [];
|
wolffd@0
|
61 end
|
wolffd@0
|
62 end
|
wolffd@0
|
63
|
wolffd@0
|
64
|
wolffd@0
|
65 % ---
|
wolffd@0
|
66 % this compability function returns the
|
wolffd@0
|
67 % mahalanobis similarity of two clip indices
|
wolffd@0
|
68 % ---
|
wolffd@0
|
69 function out = mat(m, idxa, idxb)
|
wolffd@0
|
70
|
wolffd@0
|
71 if nargin == 1
|
wolffd@0
|
72 idxa = 1:numel(m.ids);
|
wolffd@0
|
73 idxb = 1:numel(m.ids);
|
wolffd@0
|
74 end
|
wolffd@0
|
75
|
wolffd@0
|
76 % ---
|
wolffd@0
|
77 % account for different delta functions
|
wolffd@0
|
78 % ---
|
wolffd@0
|
79 if ~isempty(m.deltafun)
|
wolffd@0
|
80 out = zeros(numel(idxa),numel(idxb));
|
wolffd@0
|
81 for i=1:numel(idxa)
|
wolffd@0
|
82 for j=1:numel(idxb)
|
wolffd@0
|
83
|
wolffd@0
|
84 % calculate new distance
|
wolffd@0
|
85 tmp = m.deltafun(m.featX(:,idxa), m.featX(:,idxb),m.deltafun_params{:});
|
wolffd@0
|
86 out(i,j) = tmp' * m.mahalW * tmp;
|
wolffd@0
|
87 end
|
wolffd@0
|
88 end
|
wolffd@0
|
89 else
|
wolffd@0
|
90 % Standard Mahaldist is much faster to calculate
|
wolffd@0
|
91 out = sqdist( m.featX(:,idxa), m.featX(:,idxb), m.mahalW);
|
wolffd@0
|
92 end
|
wolffd@0
|
93 end
|
wolffd@0
|
94
|
wolffd@0
|
95 % ---
|
wolffd@0
|
96 % returns the distance for the two input clips
|
wolffd@0
|
97 % ---
|
wolffd@0
|
98 function out = distance(m, clipa, clipb)
|
wolffd@0
|
99 posa = m.get_clip_pos(clipa);
|
wolffd@0
|
100 posb = m.get_clip_pos(clipb);
|
wolffd@0
|
101
|
wolffd@0
|
102 out = m.mat(posa, posb);
|
wolffd@0
|
103 end
|
wolffd@0
|
104
|
wolffd@0
|
105 % ---
|
wolffd@0
|
106 % returns a list of n (default = 10) clips most
|
wolffd@0
|
107 % similar to the input
|
wolffd@0
|
108 % ---
|
wolffd@0
|
109 function [clips, dist] = get_nearest(m, clip, n)
|
wolffd@0
|
110 % list = get_nearest(m, clip, n)
|
wolffd@0
|
111 %
|
wolffd@0
|
112 % returns a list of n (default = 10) clips most
|
wolffd@0
|
113 % similar to the input
|
wolffd@0
|
114
|
wolffd@0
|
115 % default number of results
|
wolffd@0
|
116 if nargin == 2
|
wolffd@0
|
117
|
wolffd@0
|
118 n = 10;
|
wolffd@0
|
119 end
|
wolffd@0
|
120
|
wolffd@0
|
121 % return all clips in case n = 0
|
wolffd@0
|
122 if n == 0; n = numel(m.ids); end
|
wolffd@0
|
123
|
wolffd@0
|
124 % get clip positions
|
wolffd@0
|
125 pos = m.get_clip_pos(clip);
|
wolffd@0
|
126
|
wolffd@0
|
127 % sort according to distance
|
wolffd@0
|
128 [sc, idx] = sort( m.mat(pos, 1:numel(m.ids)), 'ascend');
|
wolffd@0
|
129
|
wolffd@0
|
130 % we only output relevant data
|
wolffd@0
|
131 idx = idx(sc < inf);
|
wolffd@0
|
132
|
wolffd@0
|
133 if numel(idx) > 0
|
wolffd@0
|
134 % create clips form best ids
|
wolffd@0
|
135 clips = MTTClip( m.ids( idx(1:min(n, end))));
|
wolffd@0
|
136 dist = m.mat(pos, idx(1:min(n, end)));
|
wolffd@0
|
137
|
wolffd@0
|
138 else
|
wolffd@0
|
139 clips = [];
|
wolffd@0
|
140 dist = [];
|
wolffd@0
|
141 end
|
wolffd@0
|
142 end
|
wolffd@0
|
143
|
wolffd@0
|
144
|
wolffd@0
|
145
|
wolffd@0
|
146 function [clips, dist] = present_nearest(m, clip, n)
|
wolffd@0
|
147 % plays and shows the n best hits for a given clip
|
wolffd@0
|
148
|
wolffd@0
|
149 % default number of results
|
wolffd@0
|
150 if nargin == 2
|
wolffd@0
|
151
|
wolffd@0
|
152 n = 3;
|
wolffd@0
|
153 end
|
wolffd@0
|
154
|
wolffd@0
|
155 % get best list
|
wolffd@0
|
156 [clips, dist] = get_nearest(m, clip, n);
|
wolffd@0
|
157
|
wolffd@0
|
158 clip.audio_features_basicsm.visualise();
|
wolffd@0
|
159 for i = 1:numel(clips)
|
wolffd@0
|
160 fprintf('\n\n\n- Rank %d, distance: %1.4f \n\n',i, dist(i));
|
wolffd@0
|
161
|
wolffd@0
|
162 clips(i).audio_features_basicsm.visualise();
|
wolffd@0
|
163 h = gcf();
|
wolffd@0
|
164 t = clips(i).play(20);
|
wolffd@0
|
165 pause(t);
|
wolffd@0
|
166 close(h);
|
wolffd@0
|
167 end
|
wolffd@0
|
168 end
|
wolffd@0
|
169
|
wolffd@0
|
170 function a = visualise(m)
|
wolffd@0
|
171
|
wolffd@0
|
172 figure;
|
wolffd@0
|
173
|
wolffd@0
|
174 % plot data
|
wolffd@0
|
175
|
wolffd@0
|
176 imagesc(m.mat);
|
wolffd@0
|
177
|
wolffd@0
|
178 a = gca;
|
wolffd@0
|
179 set(a,'YTick',[1:numel(m.ids)], 'YTickLabel',m.ids);
|
wolffd@0
|
180 set(a,'XTick',[1:numel(m.ids)], 'XTickLabel', m.ids);
|
wolffd@0
|
181
|
wolffd@0
|
182 axis xy;
|
wolffd@0
|
183 colormap(hot);
|
wolffd@0
|
184 end
|
wolffd@0
|
185
|
wolffd@0
|
186 % end methods
|
wolffd@0
|
187 end
|
wolffd@0
|
188
|
wolffd@0
|
189 % ---
|
wolffd@0
|
190 % private methods
|
wolffd@0
|
191 % ---
|
wolffd@0
|
192 methods(Access = private)
|
wolffd@0
|
193
|
wolffd@0
|
194 function out = get_clip_pos(m, clip)
|
wolffd@0
|
195 % returns position in mat for given clip
|
wolffd@0
|
196
|
wolffd@0
|
197 out = m.ret_ids(clip.id);
|
wolffd@0
|
198 end
|
wolffd@0
|
199
|
wolffd@0
|
200 end
|
wolffd@0
|
201
|
wolffd@0
|
202 end |