dan@0
|
1 function [results] = eventDetectionMetrics_classWiseEventBased(outputFile,GTFile)
|
dan@0
|
2
|
dan@0
|
3 % Class-wise event-based evaluation for event detection task
|
dan@0
|
4 % outputFile: the output of the event detection system
|
dan@0
|
5 % GTFile: the ground truth list of events
|
dan@0
|
6
|
dan@0
|
7 % Initialize
|
dan@0
|
8 eventID = {'alert','clearthroat','cough','doorslam','drawer','keyboard','keys',...
|
dan@0
|
9 'knock','laughter','mouse','pageturn','pendrop','phone','printer','speech','switch'};
|
dan@0
|
10
|
dan@0
|
11
|
dan@0
|
12 % Load event list from output and ground-truth
|
dan@0
|
13 [onset,offset,classNames] = loadEventsList(outputFile);
|
dan@0
|
14 [onsetGT,offsetGT,classNamesGT] = loadEventsList(GTFile);
|
dan@0
|
15
|
dan@0
|
16
|
dan@0
|
17 % Total number of detected and reference events per class
|
dan@0
|
18 Ntot = zeros(16,1);
|
dan@0
|
19 for i=1:length(onset)
|
dan@0
|
20 pos = strmatch(classNames{i}, eventID);
|
dan@0
|
21 Ntot(pos) = Ntot(pos)+1;
|
dan@0
|
22 end;
|
dan@0
|
23
|
dan@0
|
24 Nref = zeros(16,1);
|
dan@0
|
25 for i=1:length(onsetGT)
|
dan@0
|
26 pos = strmatch(classNamesGT{i}, eventID);
|
dan@0
|
27 Nref(pos) = Nref(pos)+1;
|
dan@0
|
28 end;
|
dan@0
|
29 I = find(Nref>0); % index for classes present in ground-truth
|
dan@0
|
30
|
dan@0
|
31
|
dan@0
|
32 % Number of correctly transcribed events per class, onset within a +/-100 ms range
|
dan@0
|
33 Ncorr = zeros(16,1);
|
dan@0
|
34 NcorrOff = zeros(16,1);
|
dan@0
|
35 for j=1:length(onsetGT)
|
dan@0
|
36 for i=1:length(onset)
|
dan@0
|
37
|
dan@0
|
38 if( strcmp(classNames{i},classNamesGT{j}) && (abs(onsetGT(j)-onset(i))<=0.1) )
|
dan@0
|
39 pos = strmatch(classNames{i}, eventID);
|
dan@0
|
40 Ncorr(pos) = Ncorr(pos)+1;
|
dan@0
|
41
|
dan@0
|
42 % If offset within a +/-100 ms range or within 50% of ground-truth event's duration
|
dan@0
|
43 if abs(offsetGT(j) - offset(i)) <= max(0.1, 0.5 * (offsetGT(j) - onsetGT(j)))
|
dan@0
|
44 pos = strmatch(classNames{i}, eventID);
|
dan@0
|
45 NcorrOff(pos) = NcorrOff(pos) +1;
|
dan@0
|
46 end;
|
dan@0
|
47
|
dan@0
|
48 break; % In order to not evaluate duplicates
|
dan@0
|
49
|
dan@0
|
50 end;
|
dan@0
|
51 end;
|
dan@0
|
52 end;
|
dan@0
|
53
|
dan@0
|
54
|
dan@0
|
55 % Compute onset-only class-wise event-based metrics
|
dan@0
|
56 Nfp = Ntot-Ncorr;
|
dan@0
|
57 Nfn = Nref-Ncorr;
|
dan@0
|
58 Nsubs = min(Nfp,Nfn);
|
dan@0
|
59 tempRec = Ncorr(I)./(Nref(I)+eps);
|
dan@0
|
60 tempPre = Ncorr(I)./(Ntot(I)+eps);
|
dan@0
|
61 results.Rec = mean(tempRec);
|
dan@0
|
62 results.Pre = mean(tempPre);
|
dan@0
|
63 tempF = 2*((tempPre.*tempRec)./(tempPre+tempRec+eps));
|
dan@0
|
64 results.F = mean(tempF);
|
dan@0
|
65 tempAEER = (Nfn(I)+Nfp(I)+Nsubs(I))./(Nref(I)+eps);
|
dan@0
|
66 results.AEER = mean(tempAEER);
|
dan@0
|
67
|
dan@0
|
68
|
dan@0
|
69 % Compute onset-offset class-wise event-based metrics
|
dan@0
|
70 NfpOff = Ntot-NcorrOff;
|
dan@0
|
71 NfnOff = Nref-NcorrOff;
|
dan@0
|
72 NsubsOff = min(NfpOff,NfnOff);
|
dan@0
|
73 tempRecOff = NcorrOff(I)./(Nref(I)+eps);
|
dan@0
|
74 tempPreOff = NcorrOff(I)./(Ntot(I)+eps);
|
dan@0
|
75 results.RecOff = mean(tempRecOff);
|
dan@0
|
76 results.PreOff = mean(tempPreOff);
|
dan@0
|
77 tempFOff = 2*((tempPreOff.*tempRecOff)./(tempPreOff+tempRecOff+eps));
|
dan@0
|
78 results.FOff = mean(tempFOff);
|
dan@0
|
79 tempAEEROff = (NfnOff(I)+NfpOff(I)+NsubsOff(I))./(Nref(I)+eps);
|
dan@0
|
80 results.AEEROff = mean(tempAEEROff);
|