function genobjs = tz_genobj(objects,n,param)
%TZ_GENOBJ Generate objects from a model based on input objects
%   GENOBJS = TZ_GENOBJ(OBJECTS,N) returns a cell array of N [object]s
%   which are generated by a model based on the cell array of [object]s
%   OBJECTS.
%   
%   GENOBJS = TZ_GENOBJ(OBJECTS,N,PARAM) let users specify specific
%   parameters of generating objects and has the following fields:
%       'model' - object models
%           'shape_tex' : shape and texture
%               'tz_trainshapemodel' - paramters for TZ_TRAINSHAPEMODEL
%               'tz_texsyn' - paramters for TZ_TEXSYN
%            'tex' - obtaining objects from a synthesized texture image
%            'smp' - sample object from the input objects randomly
%            'aut' - decide generating methods based on object size
%   
%   See also

%   14-May-2006 Initial write T. Zhao
%   Copyright (c) Center for Bioimage Informatics, CMU

if nargin < 2
    error('2 or 3 arguments are required')
end

if ~exist('param','var')
    param = struct([]);
end

param = ml_initparam(param, ...
    struct('model','shape_tex','hull',0,'hullshape',1));
modelsUsingTexsyn = {'shape_tex','tex'};
if ismember(param.model,modelsUsingTexsyn)
    param = ml_initparam(param,struct('tz_texsyn', ...
        struct('patchsize',[16 16])));
end

nobj = length(objects);

switch param.model
    case 'shape_tex'
        param = ml_initparam(param,struct( ...
            'tz_trainshapemodel',struct([])));
        
        for i=1:nobj
            selectedObjects = objects{i};
            objimg = tz_obj2img(selectedObjects,[]);
            if param.hull==1
                hullmask = ml_imgconvhull(im2bw(objimg));
                hullmask = imfill(hullmask,'hole');
                if param.hullshape==1
                  inputObjects{i} = tz_img2obj(hullmask);
                else
                  inputObjects{i} = objects{i};
                end
                
            else
                inputObjects{i} = objects{i};
            end
            shapes{i} = tz_obj2mxp(inputObjects{i});
        end
        shapeModel = tz_trainshapemodel(shapes,param.tz_trainshapemodel);
        for i=1:n
          
            genShape = tz_genshape(shapeModel);
            genShapeImg = imfill(tz_mxp2img(genShape),'hole');
            
            %pick up an object for texture synthesis
            objidx = randperm(nobj);
            objidx = objidx(1);
            selectedObjects = objects{objidx};
            objimg = tz_obj2img(selectedObjects,[]);
            if param.hull==1
                hullmask = ml_imgconvhull(im2bw(objimg));
                hullmask = imfill(hullmask,'hole');
            else
                hullmask = [];
            end
            
            texsize = size(genShapeImg);
            texsize = pow2(nextpow2(max(texsize)));
            texsize = [texsize texsize];
%             texsize = [256 256];
            
            param.tz_texsyn = ml_initparam(param.tz_texsyn, ...
                 struct('texsize',texsize));
            textureImage = tz_texsyn(objimg,hullmask,param.tz_texsyn);
            cropTextureImage = ...
                textureImage(1:size(genShapeImg,1),1:size(genShapeImg,2));
            genobjs{i} = tz_img2obj(cropTextureImage,genShapeImg);
        end
    case 'tex'
        param = ml_initparam(param,struct('mobjimgsize',[256 256]));
        objidcs = randperm(nobj);
        mobjImage = tz_mobj2img(objects(objidcs),param.mobjimgsize);
        textureImage = tz_texsyn(mobjImage,[],param.tz_texsyn);
        genobjs = tz_findobjs(textureImage);
    case 'smp'
        objidx = mod(randperm(n),nobj)+1;
        genobjs = objects(objidx);
    case 'aut'
        objSizes = tz_objsizes(objects);
        averageObjSize = mean(objSizes);
        
        if averageObjSize>param.sizeThreshold & length(objects)>20
            param.model = 'shape_tex';
            genobjs = tz_genobj(objects,n,param);
        else
            genobjs = tz_genobj(objects,n,struct('model','smp'));
        end
        
end
