VOC資料集mAP計算
檢測出來的bbox包含score和bbox,按照score降序排序,所以每新增一個樣本,就代表閾值降低一點(真實情況下score降低,iou不一定降低)。這樣就是可以有很多種閾值,每個閾值情況下計算一個prec和recall。
d:對模型檢測到的bbox迴圈:
j:對該bbox對應的影象(i)中所有的gt迴圈:
如果bb和bbgt有重疊:
計算ov=重疊部分面積/聯合的面積,並記錄ovmax,jmax
如果ovmax大於閾值:
如果i影象的第jmax個gt的diff(是否為diffcilut樣本)不為0
如果i影象的第jmax個gt的det為0,則tp(d)=1,標記為true positive
如果i影象的第jmax個gt的det不為0,則fp(d)=1,標記為false positive(mutlti detection)
否則,
fp(d)=1,標記為false positive
1)取樣計算
取召回率為0,0.1,0.2,...,1,計算準確率最大值(若為空,則設為0;此處的假設是prec曲線是遞減的),然後取11個點的平均。
2)auc曲線計算
填補auc曲線中的溝;(如果prec在開始出現下降,則認為此時iou<0.5是出現了誤判,iou不能作為唯一評判標準;這時將後面出現的prec的較大值往前填補)。
找到rec的突變點;計算面積
影象檢測的AP:
1. 使用區域選擇演算法(如selective search)得到候選區域
2. 對候選區域,計算每一個候選區域和標定框(groud truth)的iou
3. 設定一個iou閾值,大於這個的標為正樣本,小於的標為負樣本,由此得到一個類似於分類時的測試集
4. 將給定的測試集(正負樣本),通過分類器,算出每一個圖片是正樣本的score
5. 設定一個score閾值,大於等於此值的視作正樣本,小於的作為正樣本
6. 根據上一步的結果可以算出準確率和召回率
7. 調節score閾值,算出召回率從0到1時的準確率,得到一條曲線
8. 計算曲線的下面積 則為AP
function [rec,prec,ap] = VOCevaldet(VOCopts,id,cls,draw) % load test set [gtids,t]=textread(sprintf(VOCopts.imgsetpath,VOCopts.testset),'%s %d'); % load ground truth objects tic; npos=0; gt(length(gtids))=struct('BB',[],'diff',[],'det',[]); for i=1:length(gtids) % display progress if toc>1 fprintf('%s: pr: load: %d/%d\n',cls,i,length(gtids)); drawnow; tic; end % read annotation rec=PASreadrecord(sprintf(VOCopts.annopath,gtids{i})); % extract objects of class clsinds=strmatch(cls,{rec.objects(:).class},'exact'); gt(i).BB=cat(1,rec.objects(clsinds).bbox)'; gt(i).diff=[rec.objects(clsinds).difficult]; gt(i).det=false(length(clsinds),1); npos=npos+sum(~gt(i).diff); end % load results [ids,confidence,b1,b2,b3,b4]=textread(sprintf(VOCopts.detrespath,id,cls),'%s %f %f %f %f %f'); BB=[b1 b2 b3 b4]'; % sort detections by decreasing confidence [sc,si]=sort(-confidence); %按照score排序 ids=ids(si); BB=BB(:,si); % assign detections to ground truth objects nd=length(confidence); tp=zeros(nd,1); fp=zeros(nd,1); tic; for d=1:nd % display progress if toc>1 fprintf('%s: pr: compute: %d/%d\n',cls,d,nd); drawnow; tic; end % find ground truth image i=strmatch(ids{d},gtids,'exact'); if isempty(i) error('unrecognized image "%s"',ids{d}); elseif length(i)>1 error('multiple image "%s"',ids{d}); end % assign detection to ground truth object if any bb=BB(:,d); ovmax=-inf; for j=1:size(gt(i).BB,2) bbgt=gt(i).BB(:,j); bi=[max(bb(1),bbgt(1)) ; max(bb(2),bbgt(2)) ; min(bb(3),bbgt(3)) ; min(bb(4),bbgt(4))]; iw=bi(3)-bi(1)+1; ih=bi(4)-bi(2)+1; if iw>0 & ih>0 % compute overlap as area of intersection / area of union ua=(bb(3)-bb(1)+1)*(bb(4)-bb(2)+1)+... (bbgt(3)-bbgt(1)+1)*(bbgt(4)-bbgt(2)+1)-... iw*ih; ov=iw*ih/ua; if ov>ovmax ovmax=ov; jmax=j; end end end % assign detection as true positive/don't care/false positive if ovmax>=VOCopts.minoverlap if ~gt(i).diff(jmax) if ~gt(i).det(jmax) tp(d)=1; % true positive gt(i).det(jmax)=true; else fp(d)=1; % false positive (multiple detection) %對於同一個gt,找到了多個目標,則後續目標設為FP end end else fp(d)=1; % false positive end end % compute precision/recall fp=cumsum(fp); tp=cumsum(tp); rec=tp/npos; prec=tp./(fp+tp); % compute average precision ap=0; for t=0:0.1:1 p=max(prec(rec>=t)); if isempty(p) p=0; end ap=ap+p/11; end if draw % plot precision/recall plot(rec,prec,'-'); grid; xlabel 'recall' ylabel 'precision' title(sprintf('class: %s, subset: %s, AP = %.3f',cls,VOCopts.testset,ap)); end