Skip to content

Commit

Permalink
MatlabApi/CocoUtils.m: added gasonSplit() and gasonMerge() (along w u…
Browse files Browse the repository at this point in the history
…nderlying mex code)
  • Loading branch information
pdollar committed Jan 16, 2016
1 parent f1d9ba4 commit 179f17d
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 13 deletions.
38 changes: 37 additions & 1 deletion MatlabAPI/CocoUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@
% 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>validateMaskApi CocoUtils>gasonSplit CocoUtils>gasonMerge
%
% Microsoft COCO Toolbox. version 2.0
% Data, paper, and tutorials available at: http://mscoco.org/
Expand Down Expand Up @@ -279,6 +281,40 @@ function validateMaskApi( coco )
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 )
Expand Down
2 changes: 1 addition & 1 deletion MatlabAPI/gason.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@
% Code written by Piotr Dollar and Tsung-Yi Lin, 2015.
% Licensed under the Simplified BSD License [see coco/license.txt]

out = gasonMex( in );
out = gasonMex( 'convert', in );
82 changes: 71 additions & 11 deletions MatlabAPI/private/gasonMex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "gason.h"
#include "mex.h"
#include "string.h"
#include "math.h"
#include <cstdint>
#include <iomanip>
#include <sstream>
Expand Down Expand Up @@ -100,6 +101,27 @@ ostrm& json( ostrm &S, const char *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);
Expand Down Expand Up @@ -153,18 +175,56 @@ char* mxArrayToStringRobust( const mxArray *M ) {

void mexFunction( int nl, mxArray *pl[], int nr, const mxArray *pr[] )
{
if( nr!=1 ) mexErrMsgTxt("One input expected.");
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( mxGetClassID(pr[0])==mxCHAR_CLASS ) {
// object = mexFunction( string )

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(10); 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]);
char *endptr; JsonValue value; JsonAllocator allocator;
int status = jsonParse(str, &endptr, &value, allocator);
int status = jsonParse(str, &endptr, &val, allocator);
if( status != JSON_OK) mexErrMsgTxt(jsonStrError(status));
pl[0] = json(value); mxFree(str);
} else {
// string = mexFunction( object )
ostrm S; S << std::setprecision(10); json(S,pr[0]);
pl[0]=mxCreateStringRobust(S.str().c_str());
}
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(10);
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(10); 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.");
}
Binary file modified MatlabAPI/private/gasonMex.mexa64
Binary file not shown.
Binary file modified MatlabAPI/private/gasonMex.mexmaci64
Binary file not shown.

0 comments on commit 179f17d

Please sign in to comment.