"docs/source/en/api/pipelines/overview.mdx" did not exist on "9d8943b7e7361e8527fc662d9769707087c4bad6"
Commit 64b02fb6 authored by liangjing's avatar liangjing
Browse files

version 1

parents
Pipeline #176 failed with stages
in 0 seconds
classdef CocoUtils
% Utility functions for testing and validation of COCO code.
%
% The following utility functions are defined:
% convertPascalGt - Convert ground truth for PASCAL to COCO format.
% convertImageNetGt - Convert ground truth for ImageNet to COCO format.
% convertPascalDt - Convert detections on PASCAL to COCO format.
% convertImageNetDt - Convert detections on ImageNet to COCO format.
% validateOnPascal - Validate COCO eval code against PASCAL code.
% validateOnImageNet - Validate COCO eval code against ImageNet code.
% generateFakeDt - Generate fake detections from ground truth.
% validateMaskApi - Validate MaskApi against Matlab functions.
% gasonSplit - Split JSON file into multiple JSON files.
% gasonMerge - Merge JSON files into single JSON file.
% Help on each functions can be accessed by: "help CocoUtils>function".
%
% See also CocoApi MaskApi CocoEval CocoUtils>convertPascalGt
% CocoUtils>convertImageNetGt CocoUtils>convertPascalDt
% CocoUtils>convertImageNetDt CocoUtils>validateOnPascal
% CocoUtils>validateOnImageNet CocoUtils>generateFakeDt
% CocoUtils>validateMaskApi CocoUtils>gasonSplit CocoUtils>gasonMerge
%
% Microsoft COCO Toolbox. version 2.0
% Data, paper, and tutorials available at: http://mscoco.org/
% Code written by Piotr Dollar and Tsung-Yi Lin, 2015.
% Licensed under the Simplified BSD License [see coco/license.txt]
methods( Static )
function convertPascalGt( dataDir, year, split, annFile )
% Convert ground truth for PASCAL to COCO format.
%
% USAGE
% CocoUtils.convertPascalGt( dataDir, year, split, annFile )
%
% INPUTS
% dataDir - dir containing VOCdevkit/
% year - dataset year (e.g. '2007')
% split - dataset split (e.g. 'val')
% annFile - annotation file for writing results
if(exist(annFile,'file')), return; end
fprintf('Converting PASCAL VOC dataset... '); clk=tic;
dev=[dataDir '/VOCdevkit/']; addpath(genpath([dev '/VOCcode']));
VOCinit; C=VOCopts.classes'; catsMap=containers.Map(C,1:length(C));
f=fopen([dev '/VOC' year '/ImageSets/Main/' split '.txt']);
is=textscan(f,'%s %*s'); is=is{1}; fclose(f); n=length(is);
data=CocoUtils.initData(C,n);
for i=1:n, nm=[is{i} '.jpg'];
f=[dev '/VOC' year '/Annotations/' is{i} '.xml'];
R=PASreadrecord(f); hw=R.imgsize([2 1]); O=R.objects;
id=is{i}; id(id=='_')=[]; id=str2double(id);
ignore=[O.difficult]; bbs=cat(1,O.bbox);
t=catsMap.values({O.class}); catIds=[t{:}]; iscrowd=ignore*0;
data=CocoUtils.addData(data,nm,id,hw,catIds,ignore,iscrowd,bbs);
end
f=fopen(annFile,'w'); fwrite(f,gason(data)); fclose(f);
fprintf('DONE (t=%0.2fs).\n',toc(clk));
end
function convertImageNetGt( dataDir, year, split, annFile )
% Convert ground truth for ImageNet to COCO format.
%
% USAGE
% CocoUtils.convertImageNetGt( dataDir, year, split, annFile )
%
% INPUTS
% dataDir - dir containing ILSVRC*/ folders
% year - dataset year (e.g. '2013')
% split - dataset split (e.g. 'val')
% annFile - annotation file for writing results
if(exist(annFile,'file')), return; end
fprintf('Converting ImageNet dataset... '); clk=tic;
dev=[dataDir '/ILSVRC' year '_devkit/'];
addpath(genpath([dev '/evaluation/']));
t=[dev '/data/meta_det.mat'];
t=load(t); synsets=t.synsets(1:200); catNms={synsets.name};
catsMap=containers.Map({synsets.WNID},1:length(catNms));
if(~strcmp(split,'val')), blacklist=cell(1,2); else
f=[dev '/data/' 'ILSVRC' year '_det_validation_blacklist.txt'];
f=fopen(f); blacklist=textscan(f,'%d %s'); fclose(f);
t=catsMap.values(blacklist{2}); blacklist{2}=[t{:}];
end
if(strcmp(split,'train'))
dl=@(i) [dev '/data/det_lists/' split '_pos_' int2str(i) '.txt'];
is=cell(1,200); for i=1:200, f=fopen(dl(i));
is{i}=textscan(f,'%s %*s'); is{i}=is{i}{1}; fclose(f); end
is=unique(cat(1,is{:})); n=length(is);
else
f=fopen([dev '/data/det_lists/' split '.txt']);
is=textscan(f,'%s %*s'); is=is{1}; fclose(f); n=length(is);
end
data=CocoUtils.initData(catNms,n);
for i=1:n
f=[dataDir '/ILSVRC' year '_DET_bbox_' split '/' is{i} '.xml'];
R=VOCreadxml(f); R=R.annotation; nm=[is{i} '.JPEG'];
hw=str2double({R.size.height R.size.width});
if(~isfield(R,'object')), catIds=[]; bbs=[]; else
O=R.object; t=catsMap.values({O.name}); catIds=[t{:}];
b=[O.bndbox]; bbs=str2double({b.xmin; b.ymin; b.xmax; b.ymax})';
end
j=blacklist{2}(blacklist{1}==i); m=numel(j); b=[0 0 hw(2) hw(1)];
catIds=[j catIds]; bbs=[repmat(b,m,1); bbs]; %#ok<AGROW>
ignore=ismember(catIds,j); iscrowd=ignore*0; iscrowd(1:m)=1;
data=CocoUtils.addData(data,nm,i,hw,catIds,ignore,iscrowd,bbs);
end
f=fopen(annFile,'w'); fwrite(f,gason(data)); fclose(f);
fprintf('DONE (t=%0.2fs).\n',toc(clk));
end
function convertPascalDt( srcFiles, tarFile )
% Convert detections on PASCAL to COCO format.
%
% USAGE
% CocoUtils.convertPascalDt( srcFiles, tarFile )
%
% INPUTS
% srcFiles - source detection file(s) in PASCAL format
% tarFile - target detection file in COCO format
if(exist(tarFile,'file')), return; end; R=[];
for i=1:length(srcFiles), f=fopen(srcFiles{i},'r');
R1=textscan(f,'%d %f %f %f %f %f'); fclose(f);
[~,~,x0,y0,x1,y1]=deal(R1{:}); b=[x0-1 y0-1 x1-x0+1 y1-y0+1];
b(:,3:4)=max(b(:,3:4),1); b=mat2cell(b,ones(1,size(b,1)),4);
R=[R; struct('image_id',num2cell(R1{1}),'bbox',b,...
'category_id',i,'score',num2cell(R1{2}))]; %#ok<AGROW>
end
f=fopen(tarFile,'w'); fwrite(f,gason(R)); fclose(f);
end
function convertImageNetDt( srcFile, tarFile )
% Convert detections on ImageNet to COCO format.
%
% USAGE
% CocoUtils.convertImageNetDt( srcFile, tarFile )
%
% INPUTS
% srcFile - source detection file in ImageNet format
% tarFile - target detection file in COCO format
if(exist(tarFile,'file')), return; end; f=fopen(srcFile,'r');
R=textscan(f,'%d %d %f %f %f %f %f'); fclose(f);
[~,~,~,x0,y0,x1,y1]=deal(R{:}); b=[x0-1 y0-1 x1-x0+1 y1-y0+1];
b(:,3:4)=max(b(:,3:4),1); bbox=mat2cell(b,ones(1,size(b,1)),4);
R=struct('image_id',num2cell(R{1}),'bbox',bbox,...
'category_id',num2cell(R{2}),'score',num2cell(R{3}));
f=fopen(tarFile,'w'); fwrite(f,gason(R)); fclose(f);
end
function validateOnPascal( dataDir )
% Validate COCO eval code against PASCAL code.
%
% USAGE
% CocoUtils.validateOnPascal( dataDir )
%
% INPUTS
% dataDir - dir containing VOCdevkit/
split='val'; year='2007'; thrs=0:.001:1; T=length(thrs);
dev=[dataDir '/VOCdevkit/']; addpath(genpath([dev '/VOCcode/']));
d=pwd; cd(dev); VOCinit; cd(d); O=VOCopts; O.testset=split;
O.detrespath=[O.detrespath(1:end-10) split '_%s.txt'];
catNms=O.classes; K=length(catNms); ap=zeros(K,1);
for i=1:K, [R,P]=VOCevaldet(O,'comp3',catNms{i},0); R1=[R; inf];
P1=[P; 0]; for t=1:T, ap(i)=ap(i)+max(P1(R1>=thrs(t)))/T; end; end
srcFile=[dev '/results/VOC' year '/Main/comp3_det_' split];
resFile=[srcFile '.json']; annFile=[dev '/VOC2007/' split '.json'];
sfs=cell(1,K); for i=1:K, sfs{i}=[srcFile '_' catNms{i} '.txt']; end
CocoUtils.convertPascalGt(dataDir,year,split,annFile);
CocoUtils.convertPascalDt(sfs,resFile);
D=CocoApi(annFile); R=D.loadRes(resFile); E=CocoEval(D,R);
p=E.params; p.recThrs=thrs; p.iouThrs=.5; p.areaRng=[0 inf];
p.useSegm=0; p.maxDets=inf; E.params=p; E.evaluate(); E.accumulate();
apCoco=squeeze(mean(E.eval.precision,2)); deltas=abs(apCoco-ap);
fprintf('AP delta: mean=%.2e median=%.2e max=%.2e\n',...
mean(deltas),median(deltas),max(deltas))
if(max(deltas)>1e-2), msg='FAILED'; else msg='PASSED'; end
warning(['Eval code *' msg '* validation!']);
end
function validateOnImageNet( dataDir )
% Validate COCO eval code against ImageNet code.
%
% USAGE
% CocoUtils.validateOnImageNet( dataDir )
%
% INPUTS
% dataDir - dir containing ILSVRC*/ folders
warning(['Set pixelTolerance=0 in line 30 of eval_detection.m '...
'(and delete cache) otherwise AP will differ by >1e-4!']);
year='2013'; dev=[dataDir '/ILSVRC' year '_devkit/'];
fs = { [dev 'evaluation/demo.val.pred.det.txt']
[dataDir '/ILSVRC' year '_DET_bbox_val/']
[dev 'data/meta_det.mat']
[dev 'data/det_lists/val.txt']
[dev 'data/ILSVRC' year '_det_validation_blacklist.txt']
[dev 'data/ILSVRC' year '_det_validation_cache.mat'] };
addpath(genpath([dev 'evaluation/']));
ap=eval_detection(fs{:})';
resFile=[fs{1}(1:end-3) 'json'];
annFile=[dev 'data/ILSVRC' year '_val.json'];
CocoUtils.convertImageNetDt(fs{1},resFile);
CocoUtils.convertImageNetGt(dataDir,year,'val',annFile)
D=CocoApi(annFile); R=D.loadRes(resFile); E=CocoEval(D,R);
p=E.params; p.recThrs=0:.0001:1; p.iouThrs=.5; p.areaRng=[0 inf];
p.useSegm=0; p.maxDets=inf; E.params=p; E.evaluate(); E.accumulate();
apCoco=squeeze(mean(E.eval.precision,2)); deltas=abs(apCoco-ap);
fprintf('AP delta: mean=%.2e median=%.2e max=%.2e\n',...
mean(deltas),median(deltas),max(deltas))
if(max(deltas)>1e-4), msg='FAILED'; else msg='PASSED'; end
warning(['Eval code *' msg '* validation!']);
end
function generateFakeDt( coco, dtFile, varargin )
% Generate fake detections from ground truth.
%
% USAGE
% CocoUtils.generateFakeDt( coco, dtFile, varargin )
%
% INPUTS
% coco - instance of CocoApi containing ground truth
% dtFile - target file for writing detection results
% params - parameters (struct or name/value pairs)
% .n - [100] number images for which to generate dets
% .fn - [.20] false negative rate (0<fn<1)
% .fp - [.10] false positive rate (0<fp<fn)
% .sigma - [.10] translation noise (relative to object width)
% .seed - [0] random seed for reproducibility
% .type - ['bbox'] can be 'bbox', 'segm', or 'keypoints'
fprintf('Generating fake detection data... '); clk=tic;
def={'n',100,'fn',.20,'fp',.10,'sigma',.10,'seed',0,'type','bbox'};
opts=getPrmDflt(varargin,def,1); n=opts.n;
if(strcmp(opts.type,'segm')), opts.type='segmentation'; end
assert(any(strcmp(opts.type,{'bbox','segmentation','keypoints'})));
rstream = RandStream('mrg32k3a','Seed',opts.seed); k=n*100;
R=struct('image_id',[],'category_id',[],opts.type,[],'score',[]);
imgIds=sort(coco.getImgIds()); imgIds=imgIds(1:n); R=repmat(R,1,k);
imgs=coco.loadImgs(imgIds); catIds=coco.getCatIds(); k=0;
for i=1:n
A=coco.loadAnns(coco.getAnnIds('imgIds',imgIds(i),'iscrowd',0));
m=length(A); h=imgs(i).height; w=imgs(i).width;
for j=1:m, t=rand(rstream);
if(t<opts.fp), catId=catIds(randi(rstream,length(catIds)));
elseif(t<opts.fn), continue; else catId=A(j).category_id; end
bb=A(j).bbox; dx=round(randn(rstream)*opts.sigma*bb(3));
if( strcmp(opts.type,'bbox') )
x0=max(0,bb(1)+dx); x1=min(w-1,bb(1)+bb(3)+dx-1);
bb(1)=x0; bb(3)=x1-x0+1; if(bb(3)==0), continue; end; o=bb;
elseif( strcmp(opts.type,'segmentation') )
M=MaskApi.decode(MaskApi.frPoly(A(j).segmentation,h,w)); T=M*0;
T(:,max(1,1+dx):min(w,w+dx))=M(:,max(1,1-dx):min(w,w-dx));
if(nnz(T)==0), continue; end; o=MaskApi.encode(T);
elseif( strcmp(opts.type,'keypoints') )
o=A(j).keypoints; v=o(3:3:end)>0; if(~any(v)), continue; end
x=o(1:3:end); y=o(2:3:end); x(~v)=mean(x(v)); y(~v)=mean(y(v));
x=max(0,min(w-1,x+dx)); o(1:3:end)=x; o(2:3:end)=y;
end
k=k+1; R(k).image_id=imgIds(i); R(k).category_id=catId;
R(k).(opts.type)=o; R(k).score=round(rand(rstream)*1000)/1000;
end
end
R=R(1:k); f=fopen(dtFile,'w'); fwrite(f,gason(R)); fclose(f);
fprintf('DONE (t=%0.2fs).\n',toc(clk));
end
function validateMaskApi( coco )
% Validate MaskApi against Matlab functions.
%
% USAGE
% CocoUtils.validateMaskApi( coco )
%
% INPUTS
% coco - instance of CocoApi containing ground truth
S=coco.data.annotations; S=S(~[S.iscrowd]); S={S.segmentation};
h=1000; n=1000; Z=cell(1,n); A=Z; B=Z; M=Z; IB=zeros(1,n);
fprintf('Running MaskApi implementations... '); clk=tic;
for i=1:n, A{i}=MaskApi.frPoly(S{i},h,h); end
Ia=MaskApi.iou(A{1},[A{:}]);
fprintf('DONE (t=%0.2fs).\n',toc(clk));
fprintf('Running Matlab implementations... '); clk=tic;
for i=1:n, M1=0; for j=1:length(S{i}), x=S{i}{j}+.5;
M1=M1+poly2mask(x(1:2:end),x(2:2:end),h,h); end
M{i}=uint8(M1>0); B{i}=MaskApi.encode(M{i});
IB(i)=sum(sum(M{1}&M{i}))/sum(sum(M{1}|M{i}));
end
fprintf('DONE (t=%0.2fs).\n',toc(clk));
if(isequal(A,B)&&isequal(Ia,IB)),
msg='PASSED'; else msg='FAILED'; end
warning(['MaskApi *' msg '* validation!']);
end
function gasonSplit( name, k )
% Split JSON file into multiple JSON files.
%
% Splits file 'name.json' into multiple files 'name-*.json'. Only
% works for JSON arrays. Memory efficient. Inverted by gasonMerge().
%
% USAGE
% CocoUtils.gasonSplit( name, k )
%
% INPUTS
% name - file containing JSON array (w/o '.json' ext)
% k - number of files to split JSON into
s=gasonMex('split',fileread([name '.json']),k); k=length(s);
for i=1:k, f=fopen(sprintf('%s-%06i.json',name,i),'w');
fwrite(f,s{i}); fclose(f); end
end
function gasonMerge( name )
% Merge JSON files into single JSON file.
%
% Merge files 'name-*.json' into single file 'name.json'. Only works
% for JSON arrays. Memory efficient. Inverted by gasonSplit().
%
% USAGE
% CocoUtils.gasonMerge( name )
%
% INPUTS
% name - files containing JSON arrays (w/o '.json' ext)
s=dir([name '-*.json']); s=sort({s.name}); k=length(s);
p=fileparts(name); for i=1:k, s{i}=fullfile(p,s{i}); end
for i=1:k, s{i}=fileread(s{i}); end; s=gasonMex('merge',s);
f=fopen([name '.json'],'w'); fwrite(f,s); fclose(f);
end
end
methods( Static, Access=private )
function data = initData( catNms, n )
% Helper for convert() functions: init annotations.
m=length(catNms); ms=num2cell(1:m);
I = struct('file_name',0,'height',0,'width',0,'id',0);
C = struct('supercategory','none','id',ms,'name',catNms);
A = struct('segmentation',0,'area',0,'iscrowd',0,...
'image_id',0,'bbox',0,'category_id',0,'id',0,'ignore',0);
I=repmat(I,1,n); A=repmat(A,1,n*20);
data = struct('images',I,'type','instances',...
'annotations',A,'categories',C,'nImgs',0,'nAnns',0);
end
function data = addData( data,nm,id,hw,catIds,ignore,iscrowd,bbs )
% Helper for convert() functions: add annotations.
data.nImgs=data.nImgs+1;
data.images(data.nImgs)=struct('file_name',nm,...
'height',hw(1),'width',hw(2),'id',id);
for j=1:length(catIds), data.nAnns=data.nAnns+1; k=data.nAnns;
b=bbs(j,:); b=b-1; b(3:4)=b(3:4)-b(1:2)+1;
x1=b(1); x2=b(1)+b(3); y1=b(2); y2=b(2)+b(4);
S={{[x1 y1 x1 y2 x2 y2 x2 y1]}}; a=b(3)*b(4);
data.annotations(k)=struct('segmentation',S,'area',a,...
'iscrowd',iscrowd(j),'image_id',id,'bbox',b,...
'category_id',catIds(j),'id',k,'ignore',ignore(j));
end
if( data.nImgs == length(data.images) )
data.annotations=data.annotations(1:data.nAnns);
data=rmfield(data,{'nImgs','nAnns'});
end
end
end
end
classdef MaskApi
% Interface for manipulating masks stored in RLE format.
%
% RLE is a simple yet efficient format for storing binary masks. RLE
% first divides a vector (or vectorized image) into a series of piecewise
% constant regions and then for each piece simply stores the length of
% that piece. For example, given M=[0 0 1 1 1 0 1] the RLE counts would
% be [2 3 1 1], or for M=[1 1 1 1 1 1 0] the counts would be [0 6 1]
% (note that the odd counts are always the numbers of zeros). Instead of
% storing the counts directly, additional compression is achieved with a
% variable bitrate representation based on a common scheme called LEB128.
%
% Compression is greatest given large piecewise constant regions.
% Specifically, the size of the RLE is proportional to the number of
% *boundaries* in M (or for an image the number of boundaries in the y
% direction). Assuming fairly simple shapes, the RLE representation is
% O(sqrt(n)) where n is number of pixels in the object. Hence space usage
% is substantially lower, especially for large simple objects (large n).
%
% Many common operations on masks can be computed directly using the RLE
% (without need for decoding). This includes computations such as area,
% union, intersection, etc. All of these operations are linear in the
% size of the RLE, in other words they are O(sqrt(n)) where n is the area
% of the object. Computing these operations on the original mask is O(n).
% Thus, using the RLE can result in substantial computational savings.
%
% The following API functions are defined:
% encode - Encode binary masks using RLE.
% decode - Decode binary masks encoded via RLE.
% merge - Compute union or intersection of encoded masks.
% iou - Compute intersection over union between masks.
% nms - Compute non-maximum suppression between ordered masks.
% area - Compute area of encoded masks.
% toBbox - Get bounding boxes surrounding encoded masks.
% frBbox - Convert bounding boxes to encoded masks.
% frPoly - Convert polygon to encoded mask.
%
% Usage:
% Rs = MaskApi.encode( masks )
% masks = MaskApi.decode( Rs )
% R = MaskApi.merge( Rs, [intersect=false] )
% o = MaskApi.iou( dt, gt, [iscrowd=false] )
% keep = MaskApi.nms( dt, thr )
% a = MaskApi.area( Rs )
% bbs = MaskApi.toBbox( Rs )
% Rs = MaskApi.frBbox( bbs, h, w )
% R = MaskApi.frPoly( poly, h, w )
%
% In the API the following formats are used:
% R,Rs - [struct] Run-length encoding of binary mask(s)
% masks - [hxwxn] Binary mask(s) (must have type uint8)
% bbs - [nx4] Bounding box(es) stored as [x y w h]
% poly - Polygon stored as {[x1 y1 x2 y2...],[x1 y1 ...],...}
% dt,gt - May be either bounding boxes or encoded masks
% Both poly and bbs are 0-indexed (bbox=[0 0 1 1] encloses first pixel).
%
% Finally, a note about the intersection over union (iou) computation.
% The standard iou of a ground truth (gt) and detected (dt) object is
% iou(gt,dt) = area(intersect(gt,dt)) / area(union(gt,dt))
% For "crowd" regions, we use a modified criteria. If a gt object is
% marked as "iscrowd", we allow a dt to match any subregion of the gt.
% Choosing gt' in the crowd gt that best matches the dt can be done using
% gt'=intersect(dt,gt). Since by definition union(gt',dt)=dt, computing
% iou(gt,dt,iscrowd) = iou(gt',dt) = area(intersect(gt,dt)) / area(dt)
% For crowd gt regions we use this modified criteria above for the iou.
%
% To compile use the following (some precompiled binaries are included):
% mex('CFLAGS=\$CFLAGS -Wall -std=c99','-largeArrayDims',...
% 'private/maskApiMex.c','../common/maskApi.c',...
% '-I../common/','-outdir','private');
% Please do not contact us for help with compiling.
%
% Microsoft COCO Toolbox. version 2.0
% Data, paper, and tutorials available at: http://mscoco.org/
% Code written by Piotr Dollar and Tsung-Yi Lin, 2015.
% Licensed under the Simplified BSD License [see coco/license.txt]
methods( Static )
function Rs = encode( masks )
Rs = maskApiMex( 'encode', masks );
end
function masks = decode( Rs )
masks = maskApiMex( 'decode', Rs );
end
function R = merge( Rs, varargin )
R = maskApiMex( 'merge', Rs, varargin{:} );
end
function o = iou( dt, gt, varargin )
o = maskApiMex( 'iou', dt', gt', varargin{:} );
end
function keep = nms( dt, thr )
keep = maskApiMex('nms',dt',thr);
end
function a = area( Rs )
a = maskApiMex( 'area', Rs );
end
function bbs = toBbox( Rs )
bbs = maskApiMex( 'toBbox', Rs )';
end
function Rs = frBbox( bbs, h, w )
Rs = maskApiMex( 'frBbox', bbs', h, w );
end
function R = frPoly( poly, h, w )
R = maskApiMex( 'frPoly', poly, h , w );
end
end
end
%% Demo for the CocoApi (see CocoApi.m)
%% initialize COCO api (please specify dataType/annType below)
annTypes = { 'instances', 'captions', 'person_keypoints' };
dataType='val2014'; annType=annTypes{1}; % specify dataType/annType
annFile=sprintf('../annotations/%s_%s.json',annType,dataType);
coco=CocoApi(annFile);
%% display COCO categories and supercategories
if( ~strcmp(annType,'captions') )
cats = coco.loadCats(coco.getCatIds());
nms={cats.name}; fprintf('COCO categories: ');
fprintf('%s, ',nms{:}); fprintf('\n');
nms=unique({cats.supercategory}); fprintf('COCO supercategories: ');
fprintf('%s, ',nms{:}); fprintf('\n');
end
%% get all images containing given categories, select one at random
catIds = coco.getCatIds('catNms',{'person','dog','skateboard'});
imgIds = coco.getImgIds('catIds',catIds);
imgId = imgIds(randi(length(imgIds)));
%% load and display image
img = coco.loadImgs(imgId);
I = imread(sprintf('../images/%s/%s',dataType,img.file_name));
figure(1); imagesc(I); axis('image'); set(gca,'XTick',[],'YTick',[])
%% load and display annotations
annIds = coco.getAnnIds('imgIds',imgId,'catIds',catIds,'iscrowd',[]);
anns = coco.loadAnns(annIds); coco.showAnns(anns);
%% Demo demonstrating the algorithm result formats for COCO
%% select results type for demo (either bbox or segm)
type = {'segm','bbox','keypoints'}; type = type{1}; % specify type here
fprintf('Running demo for *%s* results.\n\n',type);
%% initialize COCO ground truth api
dataDir='../'; prefix='instances'; dataType='val2014';
if(strcmp(type,'keypoints')), prefix='person_keypoints'; end
annFile=sprintf('%s/annotations/%s_%s.json',dataDir,prefix,dataType);
cocoGt=CocoApi(annFile);
%% initialize COCO detections api
resFile='%s/results/%s_%s_fake%s100_results.json';
resFile=sprintf(resFile,dataDir,prefix,dataType,type);
cocoDt=cocoGt.loadRes(resFile);
%% visialuze gt and dt side by side
imgIds=sort(cocoGt.getImgIds()); imgIds=imgIds(1:100);
imgId = imgIds(randi(100)); img = cocoGt.loadImgs(imgId);
I = imread(sprintf('%s/images/val2014/%s',dataDir,img.file_name));
figure(1); subplot(1,2,1); imagesc(I); axis('image'); axis off;
annIds = cocoGt.getAnnIds('imgIds',imgId); title('ground truth')
anns = cocoGt.loadAnns(annIds); cocoGt.showAnns(anns);
figure(1); subplot(1,2,2); imagesc(I); axis('image'); axis off;
annIds = cocoDt.getAnnIds('imgIds',imgId); title('results')
anns = cocoDt.loadAnns(annIds); cocoDt.showAnns(anns);
%% load raw JSON and show exact format for results
fprintf('results structure have the following format:\n');
res = gason(fileread(resFile)); disp(res)
%% the following command can be used to save the results back to disk
if(0), f=fopen(resFile,'w'); fwrite(f,gason(res)); fclose(f); end
%% run COCO evaluation code (see CocoEval.m)
cocoEval=CocoEval(cocoGt,cocoDt,type);
cocoEval.params.imgIds=imgIds;
cocoEval.evaluate();
cocoEval.accumulate();
cocoEval.summarize();
%% generate Derek Hoiem style analyis of false positives (slow)
if(0), cocoEval.analyze(); end
function out = gason( in )
% Convert between JSON strings and corresponding JSON objects.
%
% This parser is based on Gason written and maintained by Ivan Vashchaev:
% https://github.com/vivkin/gason
% Gason is a "lightweight and fast JSON parser for C++". Please see the
% above link for license information and additional details about Gason.
%
% Given a JSON string, gason calls the C++ parser and converts the output
% into an appropriate Matlab structure. As the parsing is performed in mex
% the resulting parser is blazingly fast. Large JSON structs (100MB+) take
% only a few seconds to parse (compared to hours for pure Matlab parsers).
%
% Given a JSON object, gason calls the C++ encoder to convert the object
% back into a JSON string representation. Nearly any Matlab struct, cell
% array, or numeric array represent a valid JSON object. Note that gason()
% can be used to go both from JSON string to JSON object and back.
%
% Gason requires C++11 to compile (for GCC this requires version 4.7 or
% later). The following command compiles the parser (may require tweaking):
% mex('CXXFLAGS=\$CXXFLAGS -std=c++11 -Wall','-largeArrayDims',...
% 'private/gasonMex.cpp','../common/gason.cpp',...
% '-I../common/','-outdir','private');
% Note the use of the "-std=c++11" flag. A number of precompiled binaries
% are included, please do not contact us for help with compiling. If needed
% you can specify a compiler by adding the option 'CXX="/usr/bin/g++"'.
%
% Note that by default JSON arrays that contain only numbers are stored as
% regular Matlab arrays. Likewise, JSON arrays that contain only objects of
% the same type are stored as Matlab struct arrays. This is much faster and
% can use considerably less memory than always using Matlab cell arrays.
%
% USAGE
% object = gason( string )
% string = gason( object )
%
% INPUTS/OUTPUTS
% string - JSON string
% object - JSON object
%
% EXAMPLE
% o = struct('first',{'piotr','ty'},'last',{'dollar','lin'})
% s = gason( o ) % convert JSON object -> JSON string
% p = gason( s ) % convert JSON string -> JSON object
%
% See also
%
% Microsoft COCO Toolbox. version 2.0
% Data, paper, and tutorials available at: http://mscoco.org/
% Code written by Piotr Dollar and Tsung-Yi Lin, 2015.
% Licensed under the Simplified BSD License [see coco/license.txt]
out = gasonMex( 'convert', in );
/**************************************************************************
* Microsoft COCO Toolbox. version 2.0
* Data, paper, and tutorials available at: http://mscoco.org/
* Code written by Piotr Dollar and Tsung-Yi Lin, 2015.
* Licensed under the Simplified BSD License [see coco/license.txt]
**************************************************************************/
#include "gason.h"
#include "mex.h"
#include "string.h"
#include "math.h"
#include <cstdint>
#include <iomanip>
#include <sstream>
typedef std::ostringstream ostrm;
typedef unsigned long siz;
typedef unsigned short ushort;
siz length( const JsonValue &a ) {
// get number of elements in JSON_ARRAY or JSON_OBJECT
siz k=0; auto n=a.toNode(); while(n) { k++; n=n->next; } return k;
}
bool isRegularObjArray( const JsonValue &a ) {
// check if all JSON_OBJECTs in JSON_ARRAY have the same fields
JsonValue o=a.toNode()->value; siz k, n; const char **keys;
n=length(o); keys=new const char*[n];
k=0; for(auto j:o) keys[k++]=j->key;
for( auto i:a ) {
if(length(i->value)!=n) return false; k=0;
for(auto j:i->value) if(strcmp(j->key,keys[k++])) return false;
}
delete [] keys; return true;
}
mxArray* json( const JsonValue &o ) {
// convert JsonValue to Matlab mxArray
siz k, m, n; mxArray *M; const char **keys;
switch( o.getTag() ) {
case JSON_NUMBER:
return mxCreateDoubleScalar(o.toNumber());
case JSON_STRING:
return mxCreateString(o.toString());
case JSON_ARRAY: {
if(!o.toNode()) return mxCreateDoubleMatrix(1,0,mxREAL);
JsonValue o0=o.toNode()->value; JsonTag tag=o0.getTag();
n=length(o); bool isRegular=true;
for(auto i:o) isRegular=isRegular && i->value.getTag()==tag;
if( isRegular && tag==JSON_OBJECT && isRegularObjArray(o) ) {
m=length(o0); keys=new const char*[m];
k=0; for(auto j:o0) keys[k++]=j->key;
M = mxCreateStructMatrix(1,n,m,keys);
k=0; for(auto i:o) { m=0; for(auto j:i->value)
mxSetFieldByNumber(M,k,m++,json(j->value)); k++; }
delete [] keys; return M;
} else if( isRegular && tag==JSON_NUMBER ) {
M = mxCreateDoubleMatrix(1,n,mxREAL); double *p=mxGetPr(M);
k=0; for(auto i:o) p[k++]=i->value.toNumber(); return M;
} else {
M = mxCreateCellMatrix(1,n);
k=0; for(auto i:o) mxSetCell(M,k++,json(i->value));
return M;
}
}
case JSON_OBJECT:
if(!o.toNode()) return mxCreateStructMatrix(1,0,0,NULL);
n=length(o); keys=new const char*[n];
k=0; for(auto i:o) keys[k++]=i->key;
M = mxCreateStructMatrix(1,1,n,keys); k=0;
for(auto i:o) mxSetFieldByNumber(M,0,k++,json(i->value));
delete [] keys; return M;
case JSON_TRUE:
return mxCreateDoubleScalar(1);
case JSON_FALSE:
return mxCreateDoubleScalar(0);
case JSON_NULL:
return mxCreateDoubleMatrix(0,0,mxREAL);
default: return NULL;
}
}
template<class T, class C> ostrm& json( ostrm &S, T *A, siz n ) {
// convert numeric array to JSON string with casting
if(n==0) { S<<"[]"; return S; } if(n==1) { S<<C(A[0]); return S; }
S<<"["; for(siz i=0; i<n-1; i++) S<<C(A[i])<<",";
S<<C(A[n-1]); S<<"]"; return S;
}
template<class T> ostrm& json( ostrm &S, T *A, siz n ) {
// convert numeric array to JSON string without casting
return json<T,T>(S,A,n);
}
ostrm& json( ostrm &S, const char *A ) {
// convert char array to JSON string (handle escape characters)
#define RPL(a,b) case a: { S << b; A++; break; }
S << "\""; while( *A>0 ) switch( *A ) {
RPL('"',"\\\""); RPL('\\',"\\\\"); RPL('/',"\\/"); RPL('\b',"\\b");
RPL('\f',"\\f"); RPL('\n',"\\n"); RPL('\r',"\\r"); RPL('\t',"\\t");
default: S << *A; A++;
}
S << "\""; return S;
}
ostrm& json( ostrm& S, const JsonValue *o ) {
// convert JsonValue to JSON string
switch( o->getTag() ) {
case JSON_NUMBER: S << o->toNumber(); return S;
case JSON_TRUE: S << "true"; return S;
case JSON_FALSE: S << "false"; return S;
case JSON_NULL: S << "null"; return S;
case JSON_STRING: return json(S,o->toString());
case JSON_ARRAY:
S << "["; for(auto i:*o) {
json(S,&i->value) << (i->next ? "," : ""); }
S << "]"; return S;
case JSON_OBJECT:
S << "{"; for(auto i:*o) {
json(S,i->key) << ":";
json(S,&i->value) << (i->next ? "," : ""); }
S << "}"; return S;
default: return S;
}
}
ostrm& json( ostrm& S, const mxArray *M ) {
// convert Matlab mxArray to JSON string
siz i, j, m, n=mxGetNumberOfElements(M);
void *A=mxGetData(M); ostrm *nms;
switch( mxGetClassID(M) ) {
case mxDOUBLE_CLASS: return json(S,(double*) A,n);
case mxSINGLE_CLASS: return json(S,(float*) A,n);
case mxINT64_CLASS: return json(S,(int64_t*) A,n);
case mxUINT64_CLASS: return json(S,(uint64_t*) A,n);
case mxINT32_CLASS: return json(S,(int32_t*) A,n);
case mxUINT32_CLASS: return json(S,(uint32_t*) A,n);
case mxINT16_CLASS: return json(S,(int16_t*) A,n);
case mxUINT16_CLASS: return json(S,(uint16_t*) A,n);
case mxINT8_CLASS: return json<int8_t,int32_t>(S,(int8_t*) A,n);
case mxUINT8_CLASS: return json<uint8_t,uint32_t>(S,(uint8_t*) A,n);
case mxLOGICAL_CLASS: return json<uint8_t,uint32_t>(S,(uint8_t*) A,n);
case mxCHAR_CLASS: return json(S,mxArrayToString(M));
case mxCELL_CLASS:
S << "["; for(i=0; i<n-1; i++) json(S,mxGetCell(M,i)) << ",";
if(n>0) json(S,mxGetCell(M,n-1)); S << "]"; return S;
case mxSTRUCT_CLASS:
if(n==0) { S<<"{}"; return S; } m=mxGetNumberOfFields(M);
if(m==0) { S<<"["; for(i=0; i<n; i++) S<<"{},"; S<<"]"; return S; }
if(n>1) S<<"["; nms=new ostrm[m];
for(j=0; j<m; j++) json(nms[j],mxGetFieldNameByNumber(M,j));
for(i=0; i<n; i++) for(j=0; j<m; j++) {
if(j==0) S << "{"; S << nms[j].str() << ":";
json(S,mxGetFieldByNumber(M,i,j)) << ((j<m-1) ? "," : "}");
if(j==m-1 && i<n-1) S<<",";
}
if(n>1) S<<"]"; delete [] nms; return S;
default:
mexErrMsgTxt( "Unknown type." ); return S;
}
}
mxArray* mxCreateStringRobust( const char* str ) {
// convert char* to Matlab string (robust version of mxCreateString)
mxArray *M; ushort *c; mwSize n[2]={1,strlen(str)};
M=mxCreateCharArray(2,n); c=(ushort*) mxGetData(M);
for( siz i=0; i<n[1]; i++ ) c[i]=str[i]; return M;
}
char* mxArrayToStringRobust( const mxArray *M ) {
// convert Matlab string to char* (robust version of mxArrayToString)
if(!mxIsChar(M)) mexErrMsgTxt("String expected.");
ushort *c=(ushort*) mxGetData(M); char* str; siz n;
n=mxGetNumberOfElements(M); str=(char*) mxMalloc(n+1);
for( siz i=0; i<n; i++ ) str[i]=c[i]; str[n]=0; return str;
}
void mexFunction( int nl, mxArray *pl[], int nr, const mxArray *pr[] )
{
char action[1024]; if(!nr) mexErrMsgTxt("Inputs expected.");
mxGetString(pr[0],action,1024); nr--; pr++;
char *endptr; JsonValue val; JsonAllocator allocator;
if( nl>1 ) mexErrMsgTxt("One output expected.");
if(!strcmp(action,"convert")) {
if( nr!=1 ) mexErrMsgTxt("One input expected.");
if( mxGetClassID(pr[0])==mxCHAR_CLASS ) {
// object = mexFunction( string )
char *str = mxArrayToStringRobust(pr[0]);
int status = jsonParse(str, &endptr, &val, allocator);
if( status != JSON_OK) mexErrMsgTxt(jsonStrError(status));
pl[0] = json(val); mxFree(str);
} else {
// string = mexFunction( object )
ostrm S; S << std::setprecision(12); json(S,pr[0]);
pl[0]=mxCreateStringRobust(S.str().c_str());
}
} else if(!strcmp(action,"split")) {
// strings = mexFunction( string, k )
if( nr!=2 ) mexErrMsgTxt("Two input expected.");
char *str = mxArrayToStringRobust(pr[0]);
int status = jsonParse(str, &endptr, &val, allocator);
if( status != JSON_OK) mexErrMsgTxt(jsonStrError(status));
if( val.getTag()!=JSON_ARRAY ) mexErrMsgTxt("Array expected");
siz i=0, t=0, n=length(val), k=(siz) mxGetScalar(pr[1]);
k=(k>n)?n:(k<1)?1:k; k=ceil(n/ceil(double(n)/k));
pl[0]=mxCreateCellMatrix(1,k); ostrm S; S<<std::setprecision(12);
for(auto o:val) {
if(!t) { S.str(std::string()); S << "["; t=ceil(double(n)/k); }
json(S,&o->value); t--; if(!o->next) t=0; S << (t ? "," : "]");
if(!t) mxSetCell(pl[0],i++,mxCreateStringRobust(S.str().c_str()));
}
} else if(!strcmp(action,"merge")) {
// string = mexFunction( strings )
if( nr!=1 ) mexErrMsgTxt("One input expected.");
if(!mxIsCell(pr[0])) mexErrMsgTxt("Cell array expected.");
siz n = mxGetNumberOfElements(pr[0]);
ostrm S; S << std::setprecision(12); S << "[";
for( siz i=0; i<n; i++ ) {
char *str = mxArrayToStringRobust(mxGetCell(pr[0],i));
int status = jsonParse(str, &endptr, &val, allocator);
if( status != JSON_OK) mexErrMsgTxt(jsonStrError(status));
if( val.getTag()!=JSON_ARRAY ) mexErrMsgTxt("Array expected");
for(auto j:val) json(S,&j->value) << (j->next ? "," : "");
mxFree(str); if(i<n-1) S<<",";
}
S << "]"; pl[0]=mxCreateStringRobust(S.str().c_str());
} else mexErrMsgTxt("Invalid action.");
}
function varargout = getPrmDflt( prm, dfs, checkExtra )
% Helper to set default values (if not already set) of parameter struct.
%
% Takes input parameters and a list of 'name'/default pairs, and for each
% 'name' for which prm has no value (prm.(name) is not a field or 'name'
% does not appear in prm list), getPrmDflt assigns the given default
% value. If default value for variable 'name' is 'REQ', and value for
% 'name' is not given, an error is thrown. See below for usage details.
%
% USAGE (nargout==1)
% prm = getPrmDflt( prm, dfs, [checkExtra] )
%
% USAGE (nargout>1)
% [ param1 ... paramN ] = getPrmDflt( prm, dfs, [checkExtra] )
%
% INPUTS
% prm - param struct or cell of form {'name1' v1 'name2' v2 ...}
% dfs - cell of form {'name1' def1 'name2' def2 ...}
% checkExtra - [0] if 1 throw error if prm contains params not in dfs
% if -1 if prm contains params not in dfs adds them
%
% OUTPUTS (nargout==1)
% prm - parameter struct with fields 'name1' through 'nameN' assigned
%
% OUTPUTS (nargout>1)
% param1 - value assigned to parameter with 'name1'
% ...
% paramN - value assigned to parameter with 'nameN'
%
% EXAMPLE
% dfs = { 'x','REQ', 'y',0, 'z',[], 'eps',1e-3 };
% prm = getPrmDflt( struct('x',1,'y',1), dfs )
% [ x y z eps ] = getPrmDflt( {'x',2,'y',1}, dfs )
%
% See also INPUTPARSER
%
% Piotr's Computer Vision Matlab Toolbox Version 2.60
% Copyright 2014 Piotr Dollar. [pdollar-at-gmail.com]
% Licensed under the Simplified BSD License [see external/bsd.txt]
if( mod(length(dfs),2) ), error('odd number of default parameters'); end
if nargin<=2, checkExtra = 0; end
% get the input parameters as two cell arrays: prmVal and prmField
if iscell(prm) && length(prm)==1, prm=prm{1}; end
if iscell(prm)
if(mod(length(prm),2)), error('odd number of parameters in prm'); end
prmField = prm(1:2:end); prmVal = prm(2:2:end);
else
if(~isstruct(prm)), error('prm must be a struct or a cell'); end
prmVal = struct2cell(prm); prmField = fieldnames(prm);
end
% get and update default values using quick for loop
dfsField = dfs(1:2:end); dfsVal = dfs(2:2:end);
if checkExtra>0
for i=1:length(prmField)
j = find(strcmp(prmField{i},dfsField));
if isempty(j), error('parameter %s is not valid', prmField{i}); end
dfsVal(j) = prmVal(i);
end
elseif checkExtra<0
for i=1:length(prmField)
j = find(strcmp(prmField{i},dfsField));
if isempty(j), j=length(dfsVal)+1; dfsField{j}=prmField{i}; end
dfsVal(j) = prmVal(i);
end
else
for i=1:length(prmField)
dfsVal(strcmp(prmField{i},dfsField)) = prmVal(i);
end
end
% check for missing values
if any(strcmp('REQ',dfsVal))
cmpArray = find(strcmp('REQ',dfsVal));
error(['Required field ''' dfsField{cmpArray(1)} ''' not specified.'] );
end
% set output
if nargout==1
varargout{1} = cell2struct( dfsVal, dfsField, 2 );
else
varargout = dfsVal;
end
all:
# install pycocotools locally
python setup.py build_ext --inplace
rm -rf build
install:
# install pycocotools to the Python site-packages
python setup.py build_ext install
rm -rf build
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment