|
@@ -1,4 +1,4 @@
|
|
|
-function selectButterflies ( s_img, s_dest, s_cacheDest )
|
|
|
+function selectButterflies ( varargin )
|
|
|
% function selectButterflies ( s_img, s_dest )
|
|
|
%
|
|
|
% BRIEF
|
|
@@ -6,37 +6,50 @@ function selectButterflies ( s_img, s_dest, s_cacheDest )
|
|
|
% folder, and keep track of everything with a small cache.
|
|
|
%
|
|
|
% INPUT
|
|
|
-% s_img -- string specifying name of image to be annotated
|
|
|
-% s_dest -- where to save cropped images to
|
|
|
+% 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
|
|
|
%
|
|
|
|
|
|
- if (nargin < 3) || isempty (s_cacheDest)
|
|
|
- s_cacheDest = './cacheButterflies.mat';
|
|
|
- end
|
|
|
+ % 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 = 3;
|
|
|
+ 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
|
|
@@ -54,25 +67,30 @@ function selectButterflies ( s_img, s_dest, s_cacheDest )
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
+ % 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'))
|
|
@@ -80,6 +98,7 @@ function selectButterflies ( s_img, s_dest, s_cacheDest )
|
|
|
end
|
|
|
|
|
|
|
|
|
+ % did user wanted to quit?
|
|
|
if ( strcmp(result,'X') )
|
|
|
return;
|
|
|
end
|
|
@@ -90,8 +109,7 @@ function selectButterflies ( s_img, s_dest, s_cacheDest )
|
|
|
s_destFig = sprintf('%s_%03d.png',s_dest, i_counter);
|
|
|
imwrite ( imTmp, s_destFig );
|
|
|
|
|
|
- % save results to cache
|
|
|
-
|
|
|
+ % save results to cache
|
|
|
cacheButterflies( i_counter ).name = s_img;
|
|
|
cacheButterflies( i_counter ).rectangle = [xmin,ymin,xmax,ymax];
|
|
|
i_counter = i_counter +1;
|
|
@@ -104,10 +122,53 @@ function selectButterflies ( s_img, s_dest, s_cacheDest )
|
|
|
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
|