function model = rgbdcrop(model)

% input
%   -category: category name
%   -instace: instance name
%   -rootdir: data directory
%   -cropdir: save directory
% output
%   -model

% crops object from color and depth images

% set parameters
category = model.category;
instance = model.instance;
rootdir = model.datadir.objdir;
maxsize = 100
numcut = 20;
binsize = 8;
coutlier = 10;
ioutlier = 5;
bboxfactor = model.bboxfactor;

disp('Cropping objects ... ...');
categorydir = [rootdir '/' category '/'];
%catmaskdir = [model.datadir.maskdir '/' category '/'];
if instance == 0  % category model
   % get data path and raw bounding boxes
   instance = bodir(categorydir);
   it = 0;
   leaveOut = round(length(instance)/2);
   for i = 1:length(instance)
       if i == leaveOut
          disp(sprintf('Leaving out instance %d',i));
          continue;
       end
       instancedir{i} = [categorydir instance(i).name];
%       instmaskdir{i} = [catmaskdir instance(i).name];
       depthname = dir([instancedir{i} '/*_clean_depth.png']);
%       pcdname = dir([instancedir{i} '/*.pcd']);
       for j = 1:size(depthname,1)
           it = it + 1;
           % generate image paths
           imdir{1,it} = [instancedir{i} '/' depthname(j).name(1:end-16) '.png'];
           % generate depth paths
           depthdir{1,it} = [instancedir{i} '/' depthname(j).name];
           % generate mask paths
%           maskdir{1,it} = [instmaskdir{i} '/' depthname(j).name(1:end-16) '_mask.png'];
%           % generate 3d path
           pcddir{1,it} = [instancedir{i} '/' depthname(j).name(1:end-16) '.pcd'];
%           % read pcd data
           datapcd = readpcd(pcddir{it});
           % compute raw bonding boxes
           if size(depthname,1) > numcut
              rawbbox(it,1) = min(datapcd(:,6))+1; % top
              rawbbox(it,2) = max(datapcd(:,6)); % bottom
              rawbbox(it,3) = min(datapcd(:,5))+1; % left
              rawbbox(it,4) = max(datapcd(:,5)); % rightend
           else
              it = it-1;
           end
       end
   end
   
   % leave outliers out
   sind = 1:size(rawbbox,1);
   [aaa,hind] = sort(rawbbox(:,2) - rawbbox(:,1), 'descend');
   [bbb,wind] = sort(rawbbox(:,4) - rawbbox(:,3), 'descend');
   sind([hind(1:coutlier) wind(1:coutlier)]) = [];

   % compute bounding box size
   height = round(max(1+rawbbox(sind,2) - rawbbox(sind,1))*bboxfactor);
   if mod(height,binsize)
      height = height + (binsize - mod(height,binsize));
   end
   width = round(max(1+rawbbox(sind,4) - rawbbox(sind,3))*bboxfactor);
   if mod(width,binsize)
      width = width + (binsize - mod(width,binsize));
   end

   maxlen = max(height,width);
   if maxlen > maxsize
      height = round(height / maxlen * maxsize);
      width = round(width / maxlen * maxsize);
   end
%   sc = min(1,maxsize/maxlen)
  
   % crop objects and get true bounding boxes
   truebbox = zeros(size(rawbbox));
   indices = 1:length(sind);
   %indices = 1:12:length(sind);
   cnt = 1;
   for i = indices
       ttt = sind(i);
       [truebbox(i,:), scale(i,1)] = gettruebbox(rawbbox(ttt,:), height, width);

%       mask = imread(maskdir{ttt});
       % crop positive images and generate virtual positive images
       im = imread(imdir{ttt});
       im = imresize(im, scale(i));
       imcrop = im(truebbox(i,1):truebbox(i,2),truebbox(i,3):truebbox(i,4),:);
       %imcrop = resize_img(im(truebbox(i,1):truebbox(i,2),truebbox(i,3):truebbox(i,4),:),maxsize);
       % gencrop(im, truebbox(i,:), imsavedir, i);
%       imwrite(imcrop, ['./cropCat/' sprintf('%04d.png',i)]);

       % crop positive depths and generate virtual positive depths
       depth = imread(depthdir{ttt});
%       depth(~mask) = 3000;
       depth = imresize(depth, scale(i));
       depthcrop = depth(truebbox(i,1):truebbox(i,2),truebbox(i,3):truebbox(i,4),:);
       %[depthcrop sc] = resize_img(depth(truebbox(i,1):truebbox(i,2),truebbox(i,3):truebbox(i,4),:),maxsize);
%       scale(i) = scale(i) * sc;
       %gencrop(depth, truebbox(i,:), depthsavedir, i);
       cfea = cropfea(imcrop, depthcrop, scale(i), model);
       if i == 1
          model.cropfea = zeros(length(cfea(:)),length(indices));
       end
       model.cropfea(:,cnt) = cfea(:);
       cnt=cnt+1;
   end

else % instance model
   instancedir = [categorydir category '_' num2str(instance)];
%   instmaskdir = [catmaskdir category '_' num2str(instance)];
   depthname = dir([instancedir '/*_clean_depth.png']);
   if ~length(depthname)
      model = [];
      return;
   end
%   pcdname = dir([instancedir '/*.pcd']);
   for i = 1:size(depthname,1)
       % generate image paths
       imdir{1,i} = [instancedir '/' depthname(i).name(1:end-16) '.png'];
       % generate depth paths
       depthdir{1,i} = [instancedir '/' depthname(i).name];
       % generate mask paths
%       maskdir{1,i} = [instmaskdir '/' depthname(i).name(1:end-16) '_mask.png'];
%       % generate 3d path
       pcddir{1,i} = [instancedir '/' depthname(i).name(1:end-16) '.pcd'];
%       % read pcd data
       datapcd = readpcd(pcddir{i});
       % compute raw bonding boxes
       if size(depthname,1) > numcut
          rawbbox(i,1) = min(datapcd(:,6))+1; % top
          rawbbox(i,2) = max(datapcd(:,6)); % bottom
          rawbbox(i,3) = min(datapcd(:,5))+1; % left
          rawbbox(i,4) = max(datapcd(:,5)); % rightend
       else
          it = it-1;
       end
   end

   % leave outliers out
   sind = 1:size(rawbbox,1);
   [aaa,hind] = sort(rawbbox(:,2) - rawbbox(:,1), 'descend');
   [bbb,wind] = sort(rawbbox(:,4) - rawbbox(:,3), 'descend');
   sind([hind(1:ioutlier) wind(1:ioutlier)]) = [];

   % compute bounding box size
   height = round(max(1+rawbbox(sind,2) - rawbbox(sind,1))*bboxfactor);
   if mod(height,binsize)
      height = height + (binsize - mod(height,binsize));
   end
   width = round(max(1+rawbbox(sind,4) - rawbbox(sind,3))*bboxfactor);
   if mod(width,binsize)
      width = width + (binsize - mod(width,binsize));
   end

   maxlen = max(height,width);
   if maxlen > maxsize
      height = round(height / maxlen * maxsize);
      width = round(width / maxlen * maxsize);
   end
%   sc = min(1,maxsize/maxlen)
 
   % crop objects and get true bounding boxes
   truebbox = zeros(size(rawbbox));
   indices = 1:length(sind);
   %indices = 1:6:length(sind);
   cnt = 1;
   for i = indices
       ttt = sind(i);
       [truebbox(i,:), scale(i,1)] = gettruebbox(rawbbox(ttt,:), height, width);

%       mask = imread(maskdir{ttt});
       % crop positive images and generate virtual positive images
       im = imread(imdir{ttt});
       im = imresize(im, scale(i));
       imcrop = im(truebbox(i,1):truebbox(i,2),truebbox(i,3):truebbox(i,4),:);
       %imcrop = resize_img(im(truebbox(i,1):truebbox(i,2),truebbox(i,3):truebbox(i,4),:),maxsize);
%       imwrite(imcrop, ['./cropInst/' sprintf('%04d.png',i)]);
       % gencrop(im, truebbox(i,:), imsavedir, i);

       % crop positive depths and generate virtual positive depths
       depth = imread(depthdir{ttt});
%       depth(~mask) = 3000;
       depth = imresize(depth, scale(i));
       depthcrop = depth(truebbox(i,1):truebbox(i,2),truebbox(i,3):truebbox(i,4),:);
       %[depthcrop sc] = resize_img(depth(truebbox(i,1):truebbox(i,2),truebbox(i,3):truebbox(i,4),:),maxsize);
%       scale(i) = scale(i) * sc;
       % gencrop(depth, truebbox(i,:), depthsavedir, i);
       cfea = cropfea(imcrop, depthcrop, scale(i), model);
       if i == 1
          model.cropfea = zeros(length(cfea(:)),length(indices));
       end
       model.cropfea(:,cnt) = cfea(:);
     
       if mod(i,300) == 0
          disp(['Current iteration is ' num2str(i)]);
       end
       cnt=cnt+1;
   end  

end

% save parameters to model
model.height = height;
model.width = width;
model.fheight = size(cfea,1);
model.fwidth = size(cfea,2);
model.dim = size(cfea,3);
 
function gencrop(im, bbox, savedir, i)

numscale = 3;
sfactor = 1.05;
scale = 0.1:0.2:0.9;
imcrop = im(bbox(1):bbox(2),bbox(3):bbox(4),:);
[m, n, d] = size(imcrop);
for s = 1:numscale
    imwrite(imcrop,[savedir sprintf('%04d_%01d.png',i,s)]);
    for t = 1:length(scale)
        ims = imresize(imcrop, scale(t));
        ims = imresize(ims, [m, n]);
        imwrite(ims,[savedir sprintf('%04d_%01d',i,s) '_' num2str(scale(t)) '.png']);
    end
    height = round(sfactor^s*(bbox(2)-bbox(1)));
    width = round(sfactor^s*(bbox(4)-bbox(3)));
    truebbox = gettruebbox(bbox, height, width);
    imcrop = im(truebbox(1):truebbox(2),truebbox(3):truebbox(4),:);
    imcrop = imresize(imcrop, [m, n]);
end

function [truebbox, scale] = gettruebbox(rawbbox, height, width)

border = 20;
scale = min(height/(rawbbox(2) - rawbbox(1) + border), width/(rawbbox(4)-rawbbox(3) + border));
rawbbox(1) = ceil(scale*rawbbox(1));
rawbbox(2) = floor(scale*rawbbox(2));
rawbbox(3) = ceil(scale*rawbbox(3));
rawbbox(4) = floor(scale*rawbbox(4));

% resize bounding boxes
diff = height - (1 + rawbbox(2) - rawbbox(1));
if mod(diff,2)
  truebbox(1) = rawbbox(1) - (diff-1)/2;
  truebbox(2) = rawbbox(2) + (diff+1)/2;
else
  truebbox(1) = rawbbox(1) - diff/2;
  truebbox(2) = rawbbox(2) + diff/2;
end

% make sure that bounding boxes are in images
if truebbox(1) < 1
   truebbox(1) = 1;
   truebbox(2) = height;
end

% resize bounding boxes
diff = width - (1 + rawbbox(4) - rawbbox(3));
if mod(diff,2) 
  truebbox(3) = rawbbox(3) - (diff-1)/2;
  truebbox(4) = rawbbox(4) + (diff+1)/2;
else
  truebbox(3) = rawbbox(3) - diff/2;
  truebbox(4) = rawbbox(4) + diff/2;
end

% make sure that bounding boxes are in images
if truebbox(3) < 1
   truebbox(3) = 1;
   truebbox(4) = width;
end

