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

你可能感兴趣的:(Faster-RCNN,CNN,目标检测)