function varargout = head_annotation_interface(varargin) % HEAD_ANNOTATION_INTERFACE Application M-file for head_annotation_interface.fig % FIG = HEAD_ANNOTATION_INTERFACE launch head_annotation_interface GUI. % HEAD_ANNOTATION_INTERFACE('callback_name', ...) invoke the named callback. % % HEAD GT INTERFACE Version 1.2 by Guillaume Lathoud - lathoud@idiap.ch % % PPM reading functions courtesy of Jean-Marc Odobez - odobez@idiap.ch % TimeCode extraction tool courtesy of Olivier Masson - masson@idiap.ch % % Last Modified by GUIDE v2.0 25-Jun-2004 14:27:01 if nargin == 0 % LAUNCH GUI % First quickly check wether or not we'll be able to extract the TimeCode information timecode_cmd = []; if isunix [s,w] = system( 'uname -s' ); w = deblank( w ); if ~s if strcmp( w, 'SunOS' ) d = dir( './TimeCodeSolaris.out' ); if ~isempty( d ) timecode_cmd = d( 1 ).name; end elseif strcmp( w, 'Linux' ) d = dir( './TimeCodeLinux.out' ); if ~isempty( d ) timecode_cmd = d( 1 ).name; end end end end if isempty( timecode_cmd ) waitfor( msgbox( 'The TimeCode extraction tool was not found. Timecode information will NOT be provided.','Warning', 'warn' ) ); end % Create the interface window fig = openfig(mfilename,'reuse'); drawnow % Use system color scheme for figure: set(fig,'Color',get(0,'defaultUicontrolBackgroundColor')); % Generate a structure of handles to pass to callbacks, and store it. handles = guihandles(fig); % Save a pointer to itself! handles.self = fig; % Move it v = get( fig, 'Position' ); set( fig, 'Position', [ 1 11 v(3:end)] ); set( fig, 'Position', [ 1 v(4)+1 v(3:end)] ); % Set to 1 for debugging handles.verbose = 0; % Store the timecode command (if any) handles.timecode_cmd = timecode_cmd; % Set version number and interface window's title handles.version = 1.1; set( fig, 'Name', sprintf( 'Head Annotation Interface %g - by lathoud@idiap.ch', handles.version ) ); % Give some instructions to the user show_guidelines( handles ); % Add a figure for the image; handles.image_fig = figure; set( handles.image_fig, 'doublebuffer', 'on' ); v = get( handles.image_fig, 'Position' ); set( handles.image_fig, 'Position', [v(1) 1 1.5*v(3:4)]); % Currently no image displayed handles.image_handle = []; handles.image_xdata = []; handles.image_ydata = []; % While ground-truthing, save to the file every N ground-truth frames handles.save_interval = 5; % Color of load/save messages handles.io_color = [ 0 0 1.0 ]; % Set to 1 to show the red box during ground-truthing handles.show_gt_box = 0; handles.gt_mode = 0; % Set default value for PPM directory & load images (if any) handles.the_dir = 'seq6_iain2_cam1'; set( handles.edit1, 'String', handles.the_dir ); set( handles.edit2, 'String', 'seq6_iain2_cam1_iain.headgt' ); % Save for future callbacks guidata(fig, handles); % Initialization done. % -------------------------------------------------- % Try to open PPM directory edit1_Callback( fig, [], handles ); % Try to read GT file refresh_contents( fig, handles ); if nargout > 0 varargout{1} = fig; end elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK try if (nargout) [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard else feval(varargin{:}); % FEVAL switchyard end catch disp(lasterr); end end % ---------------------------------------------------------------------- function show_guidelines( handles ) if handles.verbose disp( '[ head_annotation_interface:show_guidelines ]' ) end % Preliminary instructions a_string = sprintf( 'by lathoud@idiap.ch\n' ); a_string = sprintf( '%s\nWith this interface you will annotate:', a_string ); a_string = sprintf( '%s\n1) A rectangle around the head of a person.', a_string ); a_string = sprintf( '%s\n2) Whether the head is not visible at all (is_visible = 0),', a_string ); a_string = sprintf( '%s\n partially visible (is_visible = 0.5 ),', a_string ); a_string = sprintf( '%s\n or fully visible (is_visible = 1.0 ).', a_string ); a_string = sprintf( '%s\n', a_string ); a_string = sprintf( '%s\nConstraints:', a_string ); a_string = sprintf( '%s\n- make sure ALL visible pixels of the head are in the rectangle (e.g. head top, ears, chin).', a_string ); a_string = sprintf( '%s\n- make the rectangle as tight as possible.', a_string ); a_string = sprintf( '%s\n', a_string ); a_string = sprintf( '%s\nDo not worry about the colored ball marker, the focus is the head only = you can cut through the ball.', a_string ); a_string = sprintf( '%s\n', a_string ); a_string = sprintf( '%s\nThe ground-truth file is a 7-column matrix, stored in ASCII format.', a_string ); a_string = sprintf( '%s\nLoading and saving are done automatically.', a_string ); a_string = sprintf( '%s\n', a_string ); a_string = sprintf( '%s\nColor of the rectangle:', a_string ); a_string = sprintf( '%s\n- red: manual ground-truth (your input) (is_manual_gt = 1).', a_string ); a_string = sprintf( '%s\n- blue: interpolated ground-truth, e.g. from a tracker (is_manual_gt = 0).', a_string ); a_string = sprintf( '%s\n\nIMPORTANT: the various video streams do not necessarily start at the same time (frame #1). It is therefore advisable that you make sure the same time frames are annotated on the various cameras, based on the "TimeCode" field, NOT on the frame "#" field.', a_string ); waitfor( msgbox( a_string, sprintf( 'Guidelines for Head Annotation Interface %g', handles.version ) ) ); % ---------------------------------------------------------------------- %| ABOUT CALLBACKS: %| GUIDE automatically appends subfunction prototypes to this file, and %| sets objects' callback properties to call them through the FEVAL %| switchyard above. This comment describes that mechanism. %| %| Each callback subfunction declaration has the following form: %| (H, EVENTDATA, HANDLES, VARARGIN) %| %| The subfunction name is composed using the object's Tag and the %| callback type separated by '_', e.g. 'slider2_Callback', %| 'figure1_CloseRequestFcn', 'axis1_ButtondownFcn'. %| %| H is the callback object's handle (obtained using GCBO). %| %| EVENTDATA is empty, but reserved for future use. %| %| HANDLES is a structure containing handles of components in GUI using %| tags as fieldnames, e.g. handles.figure1, handles.slider2. This %| structure is created at GUI startup using GUIHANDLES and stored in %| the figure's application data using GUIDATA. A copy of the structure %| is passed to each callback. You can store additional information in %| this structure at GUI startup, and you can change the structure %| during callbacks. Call guidata(h, handles) after changing your %| copy to replace the stored original so that subsequent callbacks see %| the updates. Type "help guihandles" and "help guidata" for more %| information. %| %| VARARGIN contains any extra arguments you have passed to the %| callback. Specify the extra arguments by editing the callback %| property in the inspector. By default, GUIDE sets the property to: %| ('', gcbo, [], guidata(gcbo)) %| Add any extra arguments after the last argument, before the final %| closing parenthesis. function handles = gtfile_warning( handles ) if handles.verbose disp( '[ head_annotation_interface:gtfile_warning ]' ) end waitfor( msgbox( 'Make sure you update the GT file name as well', 'PPM directory changed' ) ); set( handles.edit2, 'ForegroundColor', 'r' ); set( handles.text5, 'String', 'Check the GT file name' ); set( handles.text5, 'ForegroundColor', 'r' ); drawnow; % -------------------------------------------------------------------- function varargout = edit1_Callback(h, eventdata, handles, varargin) if handles.verbose disp( '[ head_annotation_interface:edit1_Callback ]' ); end new_dir = get( handles.edit1, 'String' ); if ~exist( new_dir, 'dir' ) waitfor( msgbox( sprintf( [ 'Could not find directory "' new_dir '".\n\nYour input was ignored.' ] ), 'Directory nname error' ) ); set( handles.edit1, 'String', handles.the_dir ); else d = dir( fullfile( new_dir, '*.ppm' ) ); ppm_found = any( ~[ d.isdir ] ); if ~ppm_found waitfor( msgbox( sprintf( [ 'Could not find any ".ppm" files in directory "' new_dir '".\n\nYour input was ignored.' ] ), 'Directory content error' ) ); else % Refresh refresh_contents( h, handles ); gtfile_warning( handles ); end end % -------------------------------------------------------------------- function varargout = slider1_Callback(h, eventdata, handles, varargin) if handles.verbose disp( '[ head_annotation_interface:slider1_Callback ]' ) end if ~handles.gt_mode set( handles.text5, 'String', '' ); set( handles.text5, 'Foregroundcolor', [ 0 0 0 ] ); end if ~isempty( handles.the_list ) update_image( h, handles ); end % -------------------------------------------------------------------- % "Browse" button function varargout = pushbutton1_Callback(h, eventdata, handles, varargin) if handles.verbose disp( '[ head_annotation_interface:pushbutton1_Callback ]' ) end old_pwd = pwd; if ~isempty( handles.the_dir ) if exist( handles.the_dir, 'dir' ) cd( handles.the_dir ); end end [ fn, pn ]=uigetfile('*','Change directory and pick ANY file'); % Make sure the current working directory is unmodified cd( old_pwd ); if ischar( pn ) if ~exist( pn, 'dir' ) waitfor( msgbox( sprintf( [ 'Could not find directory "' pn '".\n\nYour input was ignored.' ] ), 'Directory nname error' ) ); else d = dir( fullfile( pn, '*.ppm' ) ); ppm_found = any( ~[ d.isdir ] ); if ~ppm_found waitfor( msgbox( sprintf( [ 'Could not find any ".ppm" files in directory "' pn '".\n\nYour input was ignored.' ] ), 'Directory content error' ) ); else % Store the new image directory set( handles.edit1, 'String', pn ); % Refresh refresh_contents( h, handles ); gtfile_warning( handles ); end end end % --------------------------------------------------------------------- % "Refresh" implementation function refresh_contents( h, handles ) if handles.verbose disp( '[ head_annotation_interface:refresh_contents ]' ) end the_dir = get( handles.edit1, 'String' ); d = dir( fullfile( the_dir, '*.ppm' ) ); if ~any( ~[ d.isdir ] ) handles.the_list = {}; % ---------- % Save this copy of the "handles" structure guidata( handles.figure1, handles ); else % Build a list of PPM FILES the_list = { d.name }; the_list = the_list( find( ~[ d.isdir ] ) ); % Save new list of files handles.the_dir = the_dir; handles.the_list = the_list; % Check the GT file gt_file = get( handles.edit2, 'String' ); if ~exist( gt_file, 'file' ) handles.gt_m = []; set( handles.text5, 'String', '[ New GT file - memory cleared ]' ); set( handles.text5, 'Foregroundcolor', handles.io_color ); else handles.gt_m = load( gt_file, '-ASCII' ); set( handles.text5, 'String', '[ GT file loaded into memory ]' ); set( handles.text5, 'Foregroundcolor', handles.io_color ); end % ---------- % Update slider current_value = get( handles.slider1, 'Value' ); n = length( handles.the_list ); if n < 1 set( handles.slider1, 'Visible', 'off' ); elseif n < 2 set( handles.slider1, 'Visible', 'off' ); else set( handles.slider1, 'Visible', 'on' ); end set( handles.slider1, 'SliderStep', [ 1/max(1,n), 1/max(1,n/10)] ); % ---------- % Save this copy of the "handles" structure guidata( handles.figure1, handles ); % ---------- % Remaining code: update image name and display update_image( handles.figure1, handles ); end % ---------------------------------------------------------------------- function image_ind = get_image_ind( handles ) if handles.verbose disp( '[ head_annotation_interface:get_image_ind ]' ) end n = length( handles.the_list ); image_ind = round( 1 + get( handles.slider1, 'Value' ) * (n-1) ); image_ind = max( 1, image_ind ); image_ind = min( length( handles.the_list ), image_ind ); % ---------------------------------------------------------------------- function set_image_ind( handles, new_image_ind ) if handles.verbose disp( '[ head_annotation_interface:set_image_ind ]' ) end n = length( handles.the_list ); if isempty( new_image_ind ) new_image_ind = get_image_ind( handles ); else new_image_ind = max( 1, min( n, new_image_ind( 1 ) ) ); end set( handles.edit4, 'String', num2str( new_image_ind ) ); if new_image_ind ~= get_image_ind( handles ); set( handles.slider1, 'Value', (new_image_ind-1)/ (n-1) ); update_image( gcbo, handles ); end % ---------------------------------------------------------------------- function update_image( hObject, handles ) if handles.verbose disp( '[ head_annotation_interface:update_image ]' ) end image_ind = get_image_ind( handles ); set( handles.edit4, 'String', num2str( image_ind ) ); if image_ind < 1 % Update image figure( handles.image_fig ); clf; % Update GT display set( handles.text6, 'String', '[ No GT for this frame. ]' ); else % Update image a_name = handles.the_list{ image_ind }; image_fullname = fullfile( handles.the_dir, a_name ); figure( handles.image_fig ); hold off; handles.image_handle = image( uint8( Lecture( image_fullname ) ) ); handles.image_timecode = []; if ~isempty( handles.timecode_cmd ) [s,w] = system( [ handles.timecode_cmd ' ' image_fullname ] ); handles.image_timecode = deblank( w ); end handles.image_xdata = get( handles.image_handle, 'XData' ); handles.image_ydata = get( handles.image_handle, 'YData' ); a_title = a_name; if ~isempty( handles.image_timecode ) a_title = [ a_title ' ( TimeCode ' handles.image_timecode ' )' ]; end title( a_title ); % Add a box has_gt = ~isempty( handles.gt_m ); if has_gt; ind = find( handles.gt_m(:,1) == image_ind ); has_gt = ~isempty( ind ); end if ~has_gt % Update GT display set( handles.text6, 'String', '[ No GT for this frame. ]' ); else is_manual_gt = handles.gt_m( ind, 2 ); is_visible = handles.gt_m( ind, 3 ); if is_visible hold on xybox = handles.gt_m( ind, 4:7 ); h = line( xybox( [1 1 3 3 1] ), xybox( [2 4 4 2 2] ) ); if is_visible < 0.99 set( h, 'LineStyle', '--' ); end if is_manual_gt set( h, 'Color', 'r' ); else set( h, 'Color', 'c' ); end end % Update GT display new_string = [ 'GT: [' num2str( handles.gt_m(ind,:)) ']' ]; new_string = [ new_string sprintf( '\n\nimage_ind: #%d\nis_manual_gt: %d\nis_visible: %3.1f', image_ind, is_manual_gt, is_visible ) ]; if is_visible new_string = [ new_string sprintf( '\nupper-left: ( %5.2f, %5.2f )\nlower-right: ( %5.2f, %5.2f )', xybox ) ]; end set( handles.text6, 'String', new_string); end end % Update "previous manual gt" and "next manual gt" buttons update_gt_buttons( handles ); % Update bottom text if ~handles.gt_mode & all( get( handles.text5, 'Foregroundcolor' )== [0 0 0] ) set( handles.text5, 'String', '' ); end guidata( hObject, handles ); % -------------------------------------------------------------------- function varargout = edit2_Callback(h, eventdata, handles, varargin) if handles.verbose disp( '[ head_annotation_interface:edit2_Callback ]' ) end a_string = get( handles.edit2, 'String' ); [p,n,e] = fileparts( a_string ); if ~exist( p ) waitfor( msgbox( sprintf( [ 'Directory "' p '" does not exist!\n\nYour input was ignored.' ] ), 'GT file selection error' ) ); set( handles.edit2, 'String', handles.the_dir ); else refresh_contents( h, handles ); set( handles.edit2, 'ForegroundColor', 'k' ); end % -------------------------------------------------------------------- function headgt_interval = get_headgt_interval( handles ) if handles.verbose disp( '[ head_annotation_interface:get_headgt_interval ]' ) end headgt_interval = str2num( get( handles.edit3, 'String' ) ); if isempty( headgt_interval ) headgt_interval = 12; end function varargout = edit3_Callback(h, eventdata, handles, varargin) if handles.verbose disp( '[ head_annotation_interface:edit3_Callback ]' ) end headgt_interval = get_headgt_interval( handles ); set( h, 'String', num2str( headgt_interval ) ); % Save it guidata( h, handles ); % -------------------------------------------------------------------- function show_gtmanual( handles ) if handles.verbose disp( '[ head_annotation_interface:show_gtmanual ]' ) end set( handles.text5, 'String', sprintf( 'GROUND-TRUTHING:\n[Leftbutton] then [Leftbutton] to ground-truth a fully visible head,\n[Leftbutton] then [Rightbutton] to ground-truth a partially visible head,\n[Rightbutton] for a completely occluded/invisible head,\n[Space] to skip frame,\n[Return] to exit the GT mode.' )); set( handles.text5, 'Foregroundcolor', 'k' ); function varargout = pushbutton3_Callback(h, eventdata, handles, varargin) if handles.verbose disp( '[ head_annotation_interface:pushbutton3_Callback ]' ) end if ~isfield( handles, 'gt_mode' ) | handles.gt_mode == 0 try handles.gt_mode = 1; handles.gt_count = 0; % To save regularly show_gtmanual( handles ); while handles.gt_mode figure( handles.image_fig ); set( handles.image_fig, 'Selected', 'on' ); set( handles.image_fig, 'SelectionHighlight', 'on' ); %%%%%%%%%%%%%%%%%%%% % Button 1 % Upper-left corner [x1,y1,b1] = ginput( 1 ); do_stop = isempty( b1 ); if do_stop handles.gt_mode = 0; break; end % Does the user want to skip this frame? do_skip = (b1 == 32); % "Space" key % Does the user want to end the process do_stop = (b1 > 32 ); if do_stop handles.gt_mode = 0; break; end if ~do_skip % Does the user want to mark this frame as invisible? if b1 ~= 1 % yes x1 = 0; y1 = 0; x2 = 0; y2 = 0; b2 = b1; else %no %%%%%%%%%%%%%%%%%%%% % Button 2 % Lower-right corner [x2,y2,b2] = ginput( 1 ); do_stop = isempty( b2 ); if do_stop handles.gt_mode = 0; break; end % Does the user want to skip this frame? do_skip = (b2 == 32); % "Space" key % Does the user want to end the process do_stop = (b2 > 32 ); if do_stop handles.gt_mode = 0; break; end end if ~do_skip image_ind = get_image_ind( handles ); x = [ min( x1, x2) max( x1, x2 )]; y = [ min( y1, y2) max( y1, y2 )]; b = [ b1 b2]; % Clip it within the image boundaries if ~isempty( handles.image_xdata ) x = max( handles.image_xdata( 1 ) - 0.5, x ); x = min( handles.image_xdata( 2 ) + 0.5, x ); elseif handles.verbose disp( '[ pushbutton3_Callback: for some reason "handles.image_xdata" is empty. ]' ); end if ~isempty( handles.image_ydata ) y = max( handles.image_ydata( 1 ) - 0.5, y ); y = min( handles.image_ydata( 2 ) + 0.5, y ); elseif handles.verbose disp( '[ pushbutton3_Callback: for some reason "handles.image_ydata" is empty. ]' ); end % Mark this GT was given manually is_manual_gt = 1; % is_visible: % value of 0.0 means head is invisible or completely occluded % value of 0.5 means head is partially occluded % value of 1.0 means head is fully visible is_visible = mean( b==1 ); if handles.verbose disp( sprintf( 'GT is_visible: %5.2f', is_visible ) ); end xybox = [ x(1) y(1) x(2) y(2) ]; % New line to add to the ground-truth matrix new_line = [ image_ind is_manual_gt is_visible xybox ]; if handles.show_gt_box % Display it so that the user can see right away the result of his marking figure( handles.image_fig ); hold on; hh = line( [ x(1) x(2) x(2) x(1) x(1) ], [y(1) y(1) y(2) y(2) y(1)]); set( hh, 'Color', 'r' ); end % Store it, replacing old data if needed if ~isempty( handles.gt_m ) ind = find( handles.gt_m(:,1) == image_ind ); if isempty( ind ) handles.gt_m(end+1,:) = new_line; else handles.gt_m( ind, : ) = new_line; end else handles.gt_m = new_line; end handles.gt_count = handles.gt_count+1; if handles.gt_count >= handles.save_interval % Save it to the file save_file( handles ); handles.gt_count = 0; else show_gtmanual( handles ); end end end % Move on to the next ground-truth frame slider_step = get( handles.slider1, 'SliderStep' ); slider_max = get( handles.slider1, 'Max' ); old_slider_value = get( handles.slider1, 'Value' ); new_slider_value = old_slider_value + get_headgt_interval( handles ) * slider_step( 1 ); new_slider_value = min( slider_max, new_slider_value ); set( handles.slider1, 'Value', new_slider_value ); slider1_Callback( h, eventdata, handles, varargin ); % Last frame ? if abs( new_slider_value -old_slider_value ) < eps handles.gt_mode = 0; end end set( handles.text5, 'String', '' ); % Save it to the file save_file( handles ); handles.gt_count = 0; catch handles.gt_mode = 0; set( handles.text5, 'String', '' ); disp( [ '[ pushbutton3_Callback: caught error "' lasterr '" ]' ] ); keyboard end end % Update the memory guidata( h, handles ); if handles.verbose disp( 'Exited GT mode' ); end % -------------------------------------------------- % To save the file in ASCII format, without the "e" notation function save_file( handles ) if handles.verbose disp( '[ head_annotation_interface:save_file ]' ) end gt_m = sortrows( handles.gt_m ); gt_file = get( handles.edit2, 'String' ); fid = fopen( gt_file, 'wt' ); if fid < 0 waitfor( msgbox( [ 'Could not write-open "' gt_file '"' ], 'IO error' ) ); else fprintf( fid,'%4d %4d %4.1f %10.4f %10.4f %10.4f %10.4f\n',gt_m.'); fclose( fid ); end set( handles.text5, 'String', '[ GT file saved ]' ); set( handles.text5, 'Foregroundcolor', handles.io_color ); % --- Executes during object creation, after setting all properties. function edit4_CreateFcn(hObject, eventdata, handles) % hObject handle to edit4 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called % Hint: edit controls usually have a white background on Windows. % See ISPC and COMPUTER. if isstruct( handles ) if handles.verbose disp( '[ head_annotation_interface:edit4_CreateFcn ]' ) end end if ispc set(hObject,'BackgroundColor','white'); else set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor')); end function edit4_Callback(hObject, eventdata, handles) % hObject handle to edit4 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % Hints: get(hObject,'String') returns contents of edit4 as text % str2double(get(hObject,'String')) returns contents of edit4 as a double if handles.verbose disp( '[ head_annotation_interface:edit4_Callback ]' ) end new_image_ind = str2num( get( handles.edit4, 'String' ) ); n = length( handles.the_list ); if isempty( new_image_ind ) new_image_ind = get_image_ind( handles ); else new_image_ind = max( 1, min( n, new_image_ind( 1 ) ) ); end set( handles.edit4, 'String', num2str( new_image_ind ) ); if new_image_ind ~= get_image_ind( handles ); set( handles.slider1, 'Value', (new_image_ind-1)/ (n-1) ); update_image( hObject, handles ); end if ~handles.gt_mode set( handles.text5, 'String', '' ); set( handles.text5, 'Foregroundcolor', [ 0 0 0 ] ); end % -------------------------------------------------------------------- function varargout = pushbutton5_Callback(h, eventdata, handles, varargin) if handles.verbose disp( '[ head_annotation_interface:pushbutton5_Callback ]' ) end old_pwd = pwd; pp = fileparts( get( handles.edit2, 'String' ) ); if ~isempty( pp ) if exist( pp, 'dir' ) cd( pp ); end end [ fn, pn ]=uiputfile('*.headgt','Choose GT file'); if ischar( pn ) fulln = fullfile( pn, fn ); if exist( fulln, 'dir' ) waitfor( msgbox( 'Please pick or create a FILE, not a directory!', 'GT file selection error' ) ); elseif ~exist( pn, 'dir' ) waitfor( msgbox( sprintf( [ 'Directory "' pn '" does not exist!\n\nYour input was ignored.' ] ), 'GT file selection error' ) ); else % Store the new gt file name set( handles.edit2, 'String', fulln ); % Refresh refresh_contents( h, handles ); end end % Make sure the current working directory is unmodified cd( old_pwd ); % -------------------------------------------------------------------- function pmgt_ind = get_prev_manual_gt( handles ) if handles.verbose disp( '[ head_annotation_interface:get_prev_manual_gt ]' ) end pmgt_ind = []; if isfield( handles, 'gt_m' ) if ~isempty( handles.gt_m ) image_ind = get_image_ind( handles ); ind = find( ( handles.gt_m( :,1 ) < image_ind ) & handles.gt_m(:,2) ); if ~isempty( ind ) pmgt_ind = max( handles.gt_m( ind, 1 ) ); end end end % -------------------------------------------------------------------- function nmgt_ind = get_next_manual_gt( handles ) if handles.verbose disp( '[ head_annotation_interface:get_next_manual_gt ]' ) end nmgt_ind = []; if isfield( handles, 'gt_m' ) if ~isempty( handles.gt_m ) image_ind = get_image_ind( handles ); ind = find( ( handles.gt_m( :,1 ) > image_ind ) & handles.gt_m(:,2) ); if ~isempty( ind ) nmgt_ind = min( handles.gt_m( ind, 1 ) ); end end end % -------------------------------------------------------------------- function varargout = pushbutton_prevmgt_Callback(h, eventdata, handles, varargin) if handles.verbose disp( '[ head_annotation_interface:pushbutton_prevmgt_Callback ]' ) end pmgt_ind = get_prev_manual_gt( handles ); if ~isempty( pmgt_ind ) set_image_ind( handles, pmgt_ind ); if ~handles.gt_mode set( handles.text5, 'String', '' ); set( handles.text5, 'Foregroundcolor', [ 0 0 0 ] ); end end % -------------------------------------------------------------------- function varargout = pushbutton_nextmgt_Callback(h, eventdata, handles, varargin) if handles.verbose disp( '[ head_annotation_interface:pushbutton_nextmgt_Callback ]' ) end nmgt_ind = get_next_manual_gt( handles ); if ~isempty( nmgt_ind ) set_image_ind( handles, nmgt_ind ); if ~handles.gt_mode set( handles.text5, 'String', '' ); set( handles.text5, 'Foregroundcolor', [ 0 0 0 ] ); end end % ---------------------------------------------------------------------- function update_gt_buttons( handles ) if handles.verbose disp( '[ head_annotation_interface:update_gt_buttons ]' ) end % Update GT buttons pmgt_ind = get_prev_manual_gt( handles ); if ~isempty( pmgt_ind ) set( handles.pushbutton_prevmgt, 'String', sprintf( 'Go to previous manual GT (#%d)', pmgt_ind ) ); set( handles.pushbutton_prevmgt, 'Visible', 'on' ); else set( handles.pushbutton_prevmgt, 'Visible', 'off' ); end nmgt_ind = get_next_manual_gt( handles ); if ~isempty( nmgt_ind ) set( handles.pushbutton_nextmgt, 'String', sprintf( 'Go to next manual GT (#%d)', nmgt_ind ) ); set( handles.pushbutton_nextmgt, 'Visible', 'on' ); else set( handles.pushbutton_nextmgt, 'Visible', 'off' ); end % ---------------------------------------------------------------------- function Image=Lecture(nom) % Image=Lecture(nom) : Lecture d'une image % format supporté : pgm et ceux de imread (jpeg, tiff, ...) % exemple : Im1=Lecture('lezard.pgm'); % % Pour une image brute, voir LectureRaw [s,r]=strtok(nom,'.'); while ~size(r,2)==0 [s,r]=strtok(r,'.'); end if strcmp(s,'pgm')==1 Image=double(LecturePgm(nom)); elseif strcmp(s,'ppm')==1 Image=double(LecturePnm(nom)); elseif strcmp(s,'pnm')==1 Image=double(LecturePnm(nom)); else Image=imread(nom); Image=double(Image); end % ---------------------------------------------------------------------- function Image=LecturePgm(nom) % Image=LecturePgm(nom) : Lecture d'une image au format pgm % exemple : Im1=LecturePgm('lezard.pgm'); % s=size(nom); s=s(2); while nom(s)==' ' s=s-1; end fid=fopen(nom(1:s),'r'); nl=abs(10); Ent=fscanf(fid,'%c',2); if Ent=='P5' c=fscanf(fid,'%c',1); while c~=nl, c=fscanf(fid,'%c',1); end c=fscanf(fid,'%c',1); while c=='#', while c~=nl, c=fscanf(fid,'%c',1); end c=fscanf(fid,'%c',1); end else 'Ce n''est pas un fichier pgm' end %Traitement des nombres de colonnes et de lignes dim=c; c=fscanf(fid,'%c',1); while c~=nl, dim=[dim,c]; c=fscanf(fid,'%c',1); end ndim=length(dim); nb=strtok(dim,' '); dim=dim(length(nb)+1:ndim); Nbco=str2num(nb); Nbli=str2num(dim); %On trouve 255 puis, ligne suivante, les donnees s=fscanf(fid,'%c',3); if s~='255' 'Attention, erreur de format' end c=fscanf(fid,'%c',1); while c~=nl, c=fscanf(fid,'%c',1); end %%% Recuperation des donnees dans une matrice Image=fread(fid,[Nbco,Nbli]); Image=Image'; fclose(fid); % ---------------------------------------------------------------------- function Image=LecturePnm(nom) % Image=LecturePnm(nom) : Lecture d'une image au format pnm % exemple : Im1=LecturePnm('lezard.pnm'); % s=size(nom); s=s(2); while nom(s)==' ' s=s-1; end sname=s; %stupid but works for p=0:2 fid=fopen(nom(1:sname),'r'); nl=abs(10); Ent=fscanf(fid,'%c',2); if Ent=='P6' c=fscanf(fid,'%c',1); while c~=nl, c=fscanf(fid,'%c',1); end c=fscanf(fid,'%c',1); while c=='#', while c~=nl, c=fscanf(fid,'%c',1); end c=fscanf(fid,'%c',1); end else 'Ce n''est pas un fichier ppm' end %Traitement des nombres de colonnes et de lignes dim=c; c=fscanf(fid,'%c',1); while c~=nl, dim=[dim,c]; c=fscanf(fid,'%c',1); end ndim=length(dim); nb=strtok(dim,' '); dim=dim(length(nb)+1:ndim); Nbco=str2num(nb); Nbli=str2num(dim); %On trouve 255 puis, ligne suivante, les donnees s=fscanf(fid,'%c',3); if s~='255' 'Attention, erreur de format' end c=fscanf(fid,'%c',1); while c~=nl, c=fscanf(fid,'%c',1); end %%% Recuperation des donnees dans une matrice if p==0 Image=zeros(Nbli,Nbco,3); end if p==1 sss=fread(fid,1,'uchar'); end if p==2 sss=fread(fid,2,'uchar'); end ImageR=fread(fid,[Nbco,Nbli],'uchar',2); Image(:,:,p+1)=ImageR'; fclose(fid); end % end loop on plans % -------------------------------------------------------------------- function varargout = pushbutton8_Callback(h, eventdata, handles, varargin) if handles.verbose disp( '[ head_annotation_interface:pushbutton8_Callback ]' ) end show_guidelines( handles ); % -------------------------------------------------------------------- function varargout = pushbutton9_Callback(h, eventdata, handles, varargin) if handles.verbose disp( '[ head_annotation_interface:pushbutton9_Callback ]' ) end close( handles.image_fig ); close( handles.self );