1. 程式人生 > >VOC資料集mAP計算

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