function selectButterflies ( varargin ) % function selectButterflies ( s_img, s_dest ) % % BRIEF % Select bounding boxes for images, save those guys to a specified % folder, and keep track of everything with a small cache. % % INPUT % either a struct with required fields 's_img' and optional fields % 's_dest', 's_cacheDest' % OR % combinations of 'string', value for the beforementioned fields % % OUTPUT % none % % fetch specified inputs and set default values if possible %% parse inputs myInput = parseMyInputs ( varargin{:} ); % shorten writening s_img = myInput.s_img; s_dest = myInput.s_dest; s_cacheDest = myInput.s_cacheDest; % check whether a cache is available if ( exist ( s_cacheDest ) ) load ( s_cacheDest, 'cacheButterflies', 'i_counter' ); end % current image im = imread ( s_img ); % allocated figures figImg = figure; figCrop = figure; b_continueSelection = true; % ask for 1 bounding box at a time i_numBoxesPerClick = 1; % image to be shown to the user to visualize currently selected boxes imWithBoxes = im; % i_linewidth = 4; partcolor = [255,0,0]; % if cache exists, plot the boxes belonging to the current image if ( ~exist ( 'cacheButterflies' ) ) cacheButterflies = struct( 'name', 'rectangle' ) ; else idxSameImg = strcmp ( {cacheButterflies.name}, s_img); bBox = {cacheButterflies.rectangle}; bBoxSameImg = cell2mat(bBox(idxSameImg)); imWithBoxes = drawBoxesToImg(imWithBoxes, bBoxSameImg, partcolor, i_linewidth); end if ( ~exist ( 'i_counter') ) i_counter = 1 ; end % prompt user help s_prompt = sprintf('Press enter for save+continue, r for retry, and X for abort\n'); % ask for selection as long as user is interested... while b_continueSelection % bring bbox-vis figure to front figure ( figImg ); imshow ( imWithBoxes ); % ask for a new bounding box [xmin, ymin, xmax, ymax] = clickBoundingBoxes2D ( i_numBoxesPerClick ); xmin = int32(round(xmin)); ymin = int32(round(ymin)); xmax = int32(round(xmax)); ymax = int32(round(ymax)); % crop selection and present it to user imTmp = imcrop(im, [xmin, ymin, xmax-xmin, ymax-ymin]); figure ( figCrop ); imshow ( imTmp ); % ask user for judgement (okay, retry, abort) result = input(s_prompt, 's'); while ( ~isempty(result) && (strcmp(result,'r')==0) && (strcmp(result,'X')==0) ) disp(sprintf('Retry input!\n')) result = input(s_prompt, 's'); end % did user wanted to quit? if ( strcmp(result,'X') ) return; end if ( isempty(result) ) % write current proposal s_destFig = sprintf('%s_%03d.png',s_dest, i_counter); imwrite ( imTmp, s_destFig ); % save results to cache cacheButterflies( i_counter ).name = s_img; cacheButterflies( i_counter ).rectangle = [xmin,ymin,xmax,ymax]; i_counter = i_counter +1; save ( s_cacheDest, 'cacheButterflies', 'i_counter' ); % plot current result newproposal = [xmin,ymin,xmax,ymax]; imWithBoxes = drawBoxesToImg(imWithBoxes, newproposal, partcolor, i_linewidth); end end end function myInput = parseMyInputs(varargin) if ( (nargin == 1) && isstruct( varargin{1} ) ) %% was only a struct given? If so, use it :) myInput = varargin{1}; else %% check for explicitely specified settings for i=1:2:nargin if ( strcmp ( varargin{i}, 's_img' ) ) myInput.s_img = varargin{i+1}; % elseif ( strcmp ( varargin{i}, 's_dest' ) ) myInput.s_dest = varargin{i+1}; % elseif ( strcmp ( varargin{i}, 's_cacheDest' ) ) myInput.s_cacheDest = varargin{i+1}; % end end end %% now check default stuff checkCrucialField ( myInput, 's_img' ); myInput = setFieldDefault ( myInput, 's_dest', './butterflies-' ); myInput = setFieldDefault ( myInput, 's_cacheDest', './cacheButterflies.mat' ); end function myInput = setFieldDefault ( myInput, s_fieldname, value ) if ( ~(isfield(myInput, s_fieldname) ) || isempty(myInput.(s_fieldname)) ) myInput = setfield( myInput, s_fieldname, value ); end end function checkCrucialField ( myInput, s_fieldname ) assert ( (isfield(myInput, s_fieldname) ) && ~isempty(myInput.(s_fieldname)), ... sprintf('No %s specified, aborting...', s_fieldname) ... ); end