Dimitrios@0: function [results] = eventDetectionMetrics_classWiseEventBased(outputFile,GTFile) Dimitrios@0: Dimitrios@0: Dimitrios@0: % Initialize Dimitrios@0: eventID = {'alert','clearthroat','cough','doorslam','drawer','keyboard','keys',... Dimitrios@0: 'knock','laughter','mouse','pageturn','pendrop','phone','printer','speech','switch'}; Dimitrios@0: Dimitrios@0: Dimitrios@0: % Load event list from output and ground-truth Dimitrios@0: [onset,offset,classNames] = loadEventsList(outputFile); Dimitrios@0: [onsetGT,offsetGT,classNamesGT] = loadEventsList(GTFile); Dimitrios@0: Dimitrios@0: Dimitrios@0: % Total number of detected and reference events per class Dimitrios@0: Ntot = zeros(16,1); Dimitrios@0: for i=1:length(onset) Dimitrios@0: pos = strmatch(classNames{i}, eventID); Dimitrios@0: Ntot(pos) = Ntot(pos)+1; Dimitrios@0: end; Dimitrios@0: Dimitrios@0: Nref = zeros(16,1); Dimitrios@0: for i=1:length(onsetGT) Dimitrios@0: pos = strmatch(classNamesGT{i}, eventID); Dimitrios@0: Nref(pos) = Nref(pos)+1; Dimitrios@0: end; Dimitrios@0: I = find(Nref>0); % index for classes present in ground-truth Dimitrios@0: Dimitrios@0: Dimitrios@0: % Number of correctly transcribed events per class, onset within a +/-100 ms range Dimitrios@0: Ncorr = zeros(16,1); Dimitrios@0: NcorrOff = zeros(16,1); Dimitrios@0: for j=1:length(onsetGT) Dimitrios@0: for i=1:length(onset) Dimitrios@0: Dimitrios@0: if( strcmp(classNames{i},classNamesGT{j}) && (abs(onsetGT(j)-onset(i))<=0.1) ) Dimitrios@0: pos = strmatch(classNames{i}, eventID); Dimitrios@0: Ncorr(pos) = Ncorr(pos)+1; Dimitrios@0: Dimitrios@0: % If offset within a +/-100 ms range or within 50% of ground-truth event's duration Dimitrios@0: if abs(offsetGT(j) - offset(i)) <= max(0.1, 0.5 * (offsetGT(j) - onsetGT(j))) Dimitrios@0: pos = strmatch(classNames{i}, eventID); Dimitrios@0: NcorrOff(pos) = NcorrOff(pos) +1; Dimitrios@0: end; Dimitrios@0: Dimitrios@0: break; % In order to not evaluate duplicates Dimitrios@0: Dimitrios@0: end; Dimitrios@0: end; Dimitrios@0: end; Dimitrios@0: Dimitrios@0: Dimitrios@0: % Compute onset-only class-wise event-based metrics Dimitrios@0: Nfp = Ntot-Ncorr; Dimitrios@0: Nfn = Nref-Ncorr; Dimitrios@0: Nsubs = min(Nfp,Nfn); Dimitrios@0: tempRec = Ncorr(I)./(Nref(I)+eps); Dimitrios@0: tempPre = Ncorr(I)./(Ntot(I)+eps); Dimitrios@0: results.Rec = mean(tempRec); Dimitrios@0: results.Pre = mean(tempPre); Dimitrios@0: tempF = 2*((tempPre.*tempRec)./(tempPre+tempRec+eps)); Dimitrios@0: results.F = mean(tempF); Dimitrios@0: tempAEER = (Nfn(I)+Nfp(I)+Nsubs(I))./(Nref(I)+eps); Dimitrios@0: results.AEER = mean(tempAEER); Dimitrios@0: Dimitrios@0: Dimitrios@0: % Compute onset-offset class-wise event-based metrics Dimitrios@0: NfpOff = Ntot-NcorrOff; Dimitrios@0: NfnOff = Nref-NcorrOff; Dimitrios@0: NsubsOff = min(NfpOff,NfnOff); Dimitrios@0: tempRecOff = NcorrOff(I)./(Nref(I)+eps); Dimitrios@0: tempPreOff = NcorrOff(I)./(Ntot(I)+eps); Dimitrios@0: results.RecOff = mean(tempRecOff); Dimitrios@0: results.PreOff = mean(tempPreOff); Dimitrios@0: tempFOff = 2*((tempPreOff.*tempRecOff)./(tempPreOff+tempRecOff+eps)); Dimitrios@0: results.FOff = mean(tempFOff); Dimitrios@0: tempAEEROff = (NfnOff(I)+NfpOff(I)+NsubsOff(I))./(Nref(I)+eps); Dimitrios@0: results.AEEROff = mean(tempAEEROff);