% By Philip Torr 2002 % copyright Microsoft Corp. % % %designed for the good of the world by Philip Torr based on ideas contained in % copyright Philip Torr and Microsoft Corp 2002 % % @inproceedings{Torr93b, % author = "Torr, P. H. S. and Murray, D. W.", % title = "Outlier Detection and Motion Segmentation", % booktitle = "Sensor Fusion VI", % editor = "Schenker, P. S.", % publisher = "SPIE volume 2059", % note = "Boston", % pages = {432-443}, % year = 1993 } % % % @phdthesis{Torr:thesis, % author="Torr, P. H. S.", % title="Outlier Detection and Motion Segmentation", % school=" Dept. of Engineering Science, University of Oxford", % year=1995} % % @inproceedings{Beardsley96a, % author="Beardsley, P. and Torr, P. H. S. and Zisserman, A.", % title="{3D} Model Aquisition from Extended Image Sequences", % booktitle=eccv4.2, % editor = "Buxton, B. and Cipolla R.", % publisher = "Springer--Verlag", % pages={683--695}, % year=1996} % % % @article{Torr97c, % author="Torr, P. H. S. and Murray, D. W. ", % title="The Development and Comparison of Robust Methods for Estimating the Fundamental Matrix", % journal="IJCV", % volume = 24, % number = 3, % pages = {271--300}, % year=1997 % } % % % % % @article{Torr99c, % author = "Torr, P. H. S. and Zisserman, A", % title ="MLESAC: A New Robust Estimator with Application to Estimating Image Geometry ", % journal = "CVIU", % Volume = {78}, % number = 1, % pages = {138-156}, % year = 2000} % % %MAPSAC is the Bayesian version of MLESAC, and it is easier to pronounce! % it is described in: % % @article{Torr02d, % author = "Torr, P. H. S.", % title ="Bayesian Model Estimation and Selection for Epipolar Geometry and % Generic Manifold Fitting", % journal = "IJCV", % Volume = {?}, % number = ?, % pages = {?}, % url = "http://research.microsoft.com/~philtorr/", % year = 2002} % function varargout = torr_tool(varargin) % TORR_TOOL Application M-file for torr_tool.fig % FIG = TORR_TOOL launch torr_tool GUI. % TORR_TOOL('callback_name', ...) invoke the named callback. % Last Modified by GUIDE v2.0 21-May-2002 17:58:20 if nargin == 0 % LAUNCH GUI fig = openfig(mfilename,'reuse'); % 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); %phils atuff added, initialization %corner parameters handles.n_corners = 2000; %max no of corners permitted/requested handles.n_corners1 = 0; %the actual number detected handles.n_corners2 = 0; handles.corner_sigma = 1.0; handles.corner_width = 3; %matchin parameters handles.max_disparity = 50; handles.match_half_size = 3; %F parameters: handles.no_samp = 500; % no of samples in the mapsac algorithm handles.f_threshold = 6.0; % f_threshold in the mapsac algorithm %calibration matrix handles.focal_length = 3; %first guess handles.aspect_ratio = 1; handles.ppx = 0; handles.ppy = 0; %work out calibration matrix C = [handles.aspect_ratio 0 handles.ppx; 0 1 handles.ppy; 0 0 1/handles.focal_length]; handles.C = C; %informational variables handles.n_matches = 0; %how many matches have we detected. %general parameters %debugt mode handles.debug = 1; handles.m3 = 256; %third homogeous pixel coordinate, chosen as 256 to help conditioning, see my thesis handles.pathname = ['C:\matlabR12\bin\']; if ~handles.debug helpdlg('Phil asks: "how ya diddling", first load some images') end set(handles.save_image1_button, 'Enable', 'off'); set(handles.save_image2_button, 'Enable', 'off'); set(handles.Save_Images_menu, 'Enable', 'off'); %for corners set(handles.detect_corner_button, 'Enable', 'off'); set(handles.save_corner_button, 'Enable', 'off'); set(handles.load_corner_button, 'Enable', 'on'); set(handles.corn_param_button, 'Enable', 'off'); %for correlation matches set(handles.match_button, 'Enable', 'off'); set(handles.match_param_button, 'Enable', 'on'); set(handles.manual_match_button, 'Enable', 'on'); set(handles.save_match_button, 'Enable', 'off'); set(handles.load_match_button, 'Enable', 'off'); %for F and correlation matches set(handles.mapsac_button, 'Enable', 'off'); set(handles.mapsac_parameters_button, 'Enable', 'on'); set(handles.save_F_button, 'Enable', 'off'); set(handles.display_epipolar_button, 'Enable', 'off'); set(handles.display_epipolar_button2, 'Enable', 'off'); set(handles.ImproveF_button, 'Enable', 'off'); %for SFM set(handles.sfm_button, 'Enable', 'off'); guidata(fig, handles); if nargout > 0 varargout{1} = fig; end elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK try [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard catch disp(lasterr); end end %| 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. % -------------------------------------------------------------------- %%get rid f current stuff and do it again! function varargout = start_again_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.start_again_button. clear_button_Callback(h, eventdata, handles, varargin) initialize(handles) % -------------------------------------------------------------------- function varargout = frame1_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.frame1. disp('frame1 Callback not implemented yet. O great one') %---------------------------------------------------------------------\\\ function menu_OpenImage_Callback(h,eventdata,handles,varargin) disp('loading some images your highness') load_image_button_Callback(h, eventdata, handles, varargin) %---------------------------------------------------------------------\\\ function menu_SaveImages_Callback(h,eventdata,handles,varargin) save_image1_button_Callback(h, eventdata, handles, varargin) save_image_button2_Callback(h, eventdata, handles, varargin) %---------------------------------------------------------------------\\\ function menu_display_corners_Callback(h,eventdata,handles,varargin) clear_button_Callback(h, eventdata, handles, varargin); display_corners_in_figure(handles); %---------------------------------------------------------------------\\\ function menu_display_c_matches_Callback(h,eventdata,handles,varargin) clear_button_Callback(h, eventdata, handles, varargin); display_matches(h, eventdata, handles, varargin); %---------------------------------------------------------------------\\\ function menu_display_i_matches_Callback(h,eventdata,handles,varargin) clear_button_Callback(h, eventdata, handles, varargin); display_inliers(h, eventdata, handles, varargin); %---------------------------------------------------------------------\\\ function menu_display_io_matches_Callback(h,eventdata,handles,varargin) clear_button_Callback(h, eventdata, handles, varargin); display_matches(h, eventdata, handles, varargin); display_inliers(h, eventdata, handles, varargin); %---------------------------------------------------------------------\\\ % -------------------------------------------------------------------- function display_corners_in_figure(handles) % extracting the handle of the axes in which to display the image ax_handle2 = handles.axes2; ax_handle3 = handles.axes3; ccr1 = handles.ccr1; ccr2 = handles.ccr2; axes(ax_handle2); hold on axes(ax_handle3); hold on % plot(c_col, c_row, '+'); plot(ccr1(:,1), ccr1(:,2), 'g+','Parent', ax_handle2); plot(ccr2(:,1), ccr2(:,2), 'r+','Parent', ax_handle3); axes(ax_handle2); hold off axes(ax_handle3); hold off % -------------------------------------------------------------------- function varargout = detect_corner_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.pushbutton3. disp('Calculating corners.') [ccr1] = torr_charris(handles.d1,handles.n_corners,handles.corner_width,handles.corner_sigma); [ccr2] = torr_charris(handles.d2,handles.n_corners,handles.corner_width,handles.corner_sigma); %normalize so that the centre of the image is the origin... ccr1(:,1) = ccr1(:,1) - handles.image_centrex; ccr1(:,2) = ccr1(:,2) - handles.image_centrey; ccr2(:,1) = ccr2(:,1) - handles.image_centrex; ccr2(:,2) = ccr2(:,2) - handles.image_centrey; handles.ccr1 = ccr1; handles.ccr2 = ccr2; handles.n_corners1 = length(ccr1); handles.n_corners2 = length(ccr2); display_corners_in_figure(handles) set(handles.save_corner_button, 'Enable', 'on'); set(handles.match_button, 'Enable', 'on'); set(handles.match_param_button, 'Enable', 'on'); % set(handles.manual_match_button, 'Enable', 'on'); guidata(handles.figure1, handles); % -------------------------------------------------------------------- %here is phil's code to get a file, it uses the warning dialog %it has not been properly tested function [filename, pathname] = uigetfile_name(filer,message) [filename, pathname] = uigetfile(filer,message) if isequal(filename,0)|isequal(pathname,0) %recurse [filename, pathname] = uigetfile_name(filer,message); else disp(['File ', pathname, filename, ' found']) end % -------------------------------------------------------------------- function [filename, pathname] = uiputfile_name(filer,message) [filename, pathname] = uiputfile(filer,message) if isequal(filename,0)|isequal(pathname,0) [filename, pathname] = uiputfile_name(filer,message); else disp(['File ', pathname, filename, ' has been saved']) end % -------------------------------------------------------------------- function varargout = load_demo_image_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.pushbutton5. % [filename, pathname] = uigetfile_name('*.bmp;*.jpg;*.gif','Pick an input image') % [i1,map1] = imread([pathname filename]); % % [filename, pathname] = uigetfile_name('*.bmp;*.jpg;*.gif','Pick a second input image') % [i2,map2] = imread([pathname filename]); pathname1 = ['.\']; pathname2 = ['.\']; filename1=['j1.bmp']; filename2=['j2.bmp']; load_2images(h, eventdata, handles, varargin, filename1, pathname1,filename2, pathname2); %---------------------------------------------------------------------\\\ function varargout = load_2images(h, eventdata, handles, varargin, ... filename1, pathname1,filename2, pathname2) if pathname1 == pathname2 handles.pathname = pathname1; else errordlg(['The two images should be in the same directory:' pathname1 pathname2],'not fatal'); handles.pathname = pathname1; end [i1,map1] = imread([pathname1 filename1]); [i2,map2] = imread([pathname2 filename2]); iii = size(size(i1)); if iii(2) == 3 g1 = rgb2gray(i1); disp('converting to rgb'); else g1 = i1; end iii = size(size(i2)); if iii(2) == 3 g2 = rgb2gray(i2); else g2 = i2; end %if we successfully load: set(handles.detect_corner_button, 'Enable', 'on'); set(handles.load_corner_button, 'Enable', 'on'); set(handles.corn_param_button, 'Enable', 'on'); set(handles.save_image1_button, 'Enable', 'on'); set(handles.save_image2_button, 'Enable', 'on'); set(handles.Save_Images_menu, 'Enable', 'on'); set(handles.manual_match_button, 'Enable', 'on'); set(handles.load_match_button, 'Enable', 'on'); d1 = double(g1); d2 = double(g2); % extracting the handle of the axes in which to display the image ax_handle2 = handles.axes2; axes(ax_handle2); set(get(ax_handle2, 'Title'), 'Visible', 'off'); set(get(ax_handle2, 'Title'),'String', 'fff'); [m,n] = size(d1); [m1,n1] = size(d2); if (m ~= m1) | (n ~= n1) error('images must be the same size') end axis equal; colormap(map1); image(i1, 'Parent', ax_handle2,'XData',-n/2,'YData',-m/2); % imshow(i1, 'Parent', ax_handle2); ax_handle3 = handles.axes3; axes(ax_handle3); colormap(map1); image(i2, 'Parent', ax_handle3,'XData',-n/2,'YData',-m/2); handles.image_centrex = n/2; handles.image_centrey = m/2; handles.i1 = i1; handles.i2 = i2; handles.d1 = d1; handles.d2 = d2; handles.pathname = pathname1; % saving the GUI data guidata(handles.figure1, handles); %---------------------------------------------------------------------\\\ % -------------------------------------------------------------------- function varargout = load_image_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.pushbutton5. [filename1, pathname1] = uigetfile_name('*.bmp;*.jpg;*.gif','Pick an input image') [filename2, pathname2] = uigetfile_name('*.bmp;*.jpg;*.gif','Pick a second input image') load_2images(h, eventdata, handles, varargin, filename1, pathname1,filename2, pathname2); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -------------------------------------------------------------------- function varargout = clear_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.pushbutton6. % extracting the handle of the axes in which to display the image ax_handle2 = handles.axes2; axes(ax_handle2); set(get(ax_handle2, 'Title'), 'Visible', 'off'); set(get(ax_handle2, 'Title'),'String', 'fff'); hold off image(handles.i1, 'Parent', ax_handle2,'XData',-handles.image_centrex,'YData',-handles.image_centrey); % imshow(i1, 'Parent', ax_handle2); ax_handle3 = handles.axes3; axes(ax_handle3); hold off image(handles.i2, 'Parent', ax_handle3,'XData',-handles.image_centrex,'YData',-handles.image_centrey); % -------------------------------------------------------------------- function varargout = close_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.close_button. pos_size = get(handles.figure1,'Position'); user_response = modaldlg([pos_size(1)+pos_size(3)/5 pos_size(2)+pos_size(4)/5]); switch user_response case {'no','cancel'} % take no action case 'yes' % Prepare to close GUI application window % . % . % . delete(handles.figure1) end % -------------------------------------------------------------------- function varargout = help_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.help_button. HelpPath = which('stereo.htm'); web(HelpPath); % -------------------------------------------------------------------- function varargout = corn_param_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.corn_param_button. pos_size = get(handles.figure1,'Position'); dlg_pos = [pos_size(1)+pos_size(3)/5 pos_size(2)+pos_size(4)/5]; corn_param = torr_c_menu(handles, dlg_pos); handles.n_corners = corn_param(1); handles.corner_sigma = corn_param(2); handles.corner_width = corn_param(3); corn_param % saving the GUI data guidata(handles.figure1, handles); %---------------------------------------------------------------------\\\ function save_corners_to_file(n_corners1, n_corners2, ccr1, ccr2, FID) fprintf(FID,'%1.0f \n',n_corners1); fprintf(FID,'%1.0f \n',n_corners2); fprintf(FID,'%1.1f %1.1f \n',ccr1'); fprintf(FID,'%1.1f %1.1f \n',ccr2'); % -------------------------------------------------------------------- function varargout = save_corner_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.save_corner_button. [fname,pname] = uiputfile_name('*.cor','Put Corner File'); ccr1 = handles.ccr1; ccr2 = handles.ccr2; %save([pname fname], 'n_corners', 'ccr1', 'ccr2', '-ASCII') FID = fopen([pname fname],'w'); n_corners1 = handles.n_corners1; n_corners2 = handles.n_corners2; save_corners_to_file(n_corners1, n_corners2, ccr1, ccr2, FID) fclose(FID); % -------------------------------------------------------------------- function [n_corners1, n_corners2, ccr1, ccr2] = load_corners_from_file(FID) n_corners1 = fscanf(FID,'%f',1); n_corners2 = fscanf(FID,'%f',1); ccr1 = fscanf(FID,'%f %f',[2 n_corners1]); ccr2 = fscanf(FID,'%f %f',[2 n_corners2]); % -------------------------------------------------------------------- function varargout = load_corner_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.load_corner_button. [fname,pname] = uigetfile_name('*.cor','Load Corner File'); if isempty(fname) return end FID = fopen([pname fname]); [n_corners1, n_corners2, ccr1, ccr2] = load_corners_from_file(FID); handles.n_corners1 = n_corners1; handles.n_corners2 = n_corners2; handles.ccr1 = ccr1'; handles.ccr2 = ccr2'; fclose(FID); set(handles.save_corner_button, 'Enable', 'on'); set(handles.match_button, 'Enable', 'on'); set(handles.match_param_button, 'Enable', 'on'); %once we have done the matches we can no longer redo corners otherwise things might be inconsistent set(handles.detect_corner_button, 'Enable', 'off'); % saving the GUI data guidata(handles.figure1, handles); clear_button_Callback(h, eventdata, handles, varargin); display_corners_in_figure(handles) %---------------------------------------------------------------------\\\ % -------------------------------------------------------------------- function varargout = match_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.match_button. %shift the x,y coordinates so we can access the image directly ccr1(:,1) = handles.ccr1(:,1) + handles.image_centrex; ccr1(:,2) = handles.ccr1(:,2) + handles.image_centrey; ccr2(:,1) = handles.ccr2(:,1) + handles.image_centrex; ccr2(:,2) = handles.ccr2(:,2) + handles.image_centrey; matches12 = torr_corn_matcher(handles.d1, handles.d2, ccr1, ccr2, handles.max_disparity,handles.match_half_size); disp('Number of matches:') length(matches12) matches12(:,1) = matches12(:,1) - handles.image_centrex; matches12(:,2) = matches12(:,2) - handles.image_centrey; matches12(:,3) = matches12(:,3) - handles.image_centrex; matches12(:,4) = matches12(:,4) - handles.image_centrey; handles.matches12 = matches12; handles.n_matches = length(matches12); set(handles.save_match_button, 'Enable', 'on'); set(handles.mapsac_button, 'Enable', 'on'); set(handles.mapsac_parameters_button, 'Enable', 'on'); %once we have done the matches we can no longer redo corners otherwise things might be inconsistent set(handles.detect_corner_button, 'Enable', 'off'); guidata(handles.figure1, handles); display_matches(h, eventdata, handles, varargin); % -------------------------------------------------------------------- function varargout = display_matches(h, eventdata, handles, varargin) % extracting the handle of the axes in which to display the image ax_handle2 = handles.axes2; ax_handle3 = handles.axes3; ccr1 = handles.ccr1; ccr2 = handles.ccr2; matches= handles.matches12; axes(ax_handle2); hold on axes(ax_handle3); hold on x1 = matches(:,1); y1 = matches(:,2); x2 = matches(:,3); y2 = matches(:,4); u1 = x2 - x1; v1 = y2 - y1; plot (matches(:,1), matches(:,2),'r+'); hold on plot (matches(:,3), matches(:,4),'r+'); display_numbers = 0; if display_numbers mat_index1 = 1:length(matches); mat_index1 = mat_index1'; mat_index = num2str(mat_index1); text(matches(:,1), matches(:,2),mat_index) end quiver(x1, y1, u1, v1, 0) hold off % % plot(ccr1(:,1), ccr1(:,2), 'r.') % plot(ccr2(:,1), ccr2(:,2), 'c.') % % for i = 1:length(mat12) % if mat12(i) ~= 0 % a = [ccr1(i,1),ccr2(mat12(i),1)]; %x1 x2 % b = [ccr1(i,2),ccr2(mat12(i),2)]; %y1 y2 % %x1 y1 % %x2 y2 % line(a,b); % end % end axes(ax_handle2); hold off axes(ax_handle3); hold off % -------------------------------------------------------------------- function varargout = match_param_button_Callback(h, eventdata, handles, varargin) pos_size = get(handles.figure1,'Position'); dlg_pos = [pos_size(1)+pos_size(3)/5 pos_size(2)+pos_size(4)/5]; match_param = torr_m_menu(handles, dlg_pos); handles.max_disparity = match_param(1); handles.match_half_size = match_param(2); % saving the GUI data guidata(handles.figure1, handles); %--------------------------------------------------------------------- % -------------------------------------------------------------------- function varargout = save_image1_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.save_image1_button. ax_handle2 = handles.axes2; %ax_handle3 = handles.axes3; % hf1 = figure; % %plot(sin(1:10)); %hf2 = figure; %ha = findobj('Parent',hf1); % ax_handle2 = handles.axes2; % new_axes = axes(ax_handle2); % set(new_axes, 'Parent', hf1); % % [fname,pname] = uiputfile('*.fig'); % saveas(ax_handle2,[pname fname ]); %hgsave(ax_handle2,[pname fname ]); new_fig = figure; new_axes = copyobj(ax_handle2,new_fig) %set(new_axes,'Position',[.5 .5 .8 .8],'DataAspectRatioMode','auto','PlotBoxAspectRatioMode','auto'); %get(new_axes) axis_position = get(new_axes,'Position'); set(new_axes,'Position',[10 7 axis_position(3) axis_position(4) ]); %keyboard % fff = handles.figure1; % saveas(fff,'bigfig.bmp'); % -------------------------------------------------------------------- function varargout = save_image2_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.save_image2_button. ax_handle3 = handles.axes3; % [fname,pname] = uiputfile('*.fig'); % saveas(ax_handle3,[pname fname ]); %hgsave(ax_handle3,[pname fname ]); new_fig = figure; new_axes = copyobj(ax_handle3,new_fig) %set(new_axes,'Position',[.5 .5 .8 .8],'DataAspectRatioMode','auto','PlotBoxAspectRatioMode','auto'); %get(new_axes) axis_position = get(new_axes,'Position'); set(new_axes,'Position',[10 7 axis_position(3) axis_position(4) ]); %keyboard % -------------------------------------------------------------------- function varargout = manual_match_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.manual_match_button. set(handles.save_match_button, 'Enable', 'on'); set(handles.load_match_button, 'Enable', 'on'); matches12 = torr_add_manual_matches(handles.axes2,handles.axes3); handles.matches12 = matches12; handles.n_matches = length(matches12); %also store corners ccr1(:,1) = matches12(:,1); ccr1(:,2) = matches12(:,2); ccr2(:,1) = matches12(:,3); ccr2(:,2) = matches12(:,4); handles.ccr1 = ccr1; handles.ccr2 = ccr2; %once we have done the matches we can no longer redo corners otherwise things might be inconsistent set(handles.detect_corner_button, 'Enable', 'off'); guidata(handles.figure1, handles); display_matches(h, eventdata, handles, varargin); if handles.n_matches > 7; set(handles.mapsac_button, 'Enable', 'on'); set(handles.mapsac_parameters_button, 'Enable', 'on'); set(handles.ImproveF_button, 'Enable', 'on'); end % -------------------------------------------------------------------- function varargout = save_match_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.save_corner_button. [fname,pname] = uiputfile_name('*.matches','Put Match File'); n_matches = handles.n_matches; matches12 = handles.matches12; %save([pname fname], 'n_corners', 'ccr1', 'ccr2', '-ASCII') FID = fopen([pname fname],'w'); fprintf(FID,'%1.0f \n',n_matches); fprintf(FID,'%1.1f %1.1f %1.1f %1.1f \n',matches12'); %now store original corners for good measure: n_corners = handles.n_corners; ccr1 = handles.ccr1; ccr2 = handles.ccr2; n_corners1 = handles.n_corners1; n_corners2 = handles.n_corners2; save_corners_to_file(n_corners1, n_corners2, ccr1, ccr2, FID); fclose(FID); % -------------------------------------------------------------------- function varargout = load_match_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.load_match_button. % Stub for Callback of the uicontrol handles.load_corner_button. [fname,pname] = uigetfile_name('*.matches','Load Match File'); if isempty(fname) return end FID = fopen([pname fname]); n_matches = fscanf(FID,'%f',1) handles.n_matches = n_matches; matches12 = fscanf(FID,'%f %f %f %f',[4 n_matches]); [n_corners1, n_corners2, ccr1, ccr2] = load_corners_from_file(FID); handles.n_corners1 = n_corners1; handles.n_corners2 = n_corners2; handles.ccr1 = ccr1'; handles.ccr2 = ccr2'; fclose(FID); handles.matches12 = matches12'; set(handles.save_corner_button, 'Enable', 'on'); set(handles.save_match_button, 'Enable', 'on'); set(handles.match_button, 'Enable', 'on'); set(handles.match_param_button, 'Enable', 'on'); % Stub for Callback of the uicontrol handles.pushbutton28. set(handles.mapsac_button, 'Enable', 'on'); set(handles.mapsac_parameters_button, 'Enable', 'on'); % saving the GUI data guidata(handles.figure1, handles); clear_button_Callback(h, eventdata, handles, varargin) display_matches(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = display_inliers(h, eventdata, handles, varargin) % extracting the handle of the axes in which to display the image ax_handle2 = handles.axes2; ax_handle3 = handles.axes3; ccr1 = handles.ccr1; ccr2 = handles.ccr2; axes(ax_handle2); hold on axes(ax_handle3); hold on matches12 = handles.inlier_matches; plot(matches12(:,3),matches12(:,4),'c.'); for i = 1:length(matches12) a = [matches12(i,1),matches12(i,3)]; %x1 x2 b = [matches12(i,2),matches12(i,4)]; %y1 y2 line(a,b,'Color','g'); end axes(ax_handle2); hold on plot(matches12(:,3),matches12(:,4),'c.'); %can i fix this to make this faster?? for i = 1:length(matches12) a = [matches12(i,1),matches12(i,3)]; %x1 x2 b = [matches12(i,2),matches12(i,4)]; %y1 y2 line(a,b,'Color','g'); end axes(ax_handle2); hold off axes(ax_handle3); hold off %MAPSAC is the Bayesian version of MLESAC, and it is easier to pronounce! % -------------------------------------------------------------------- function varargout = mapsac_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.mapsac_button. %run mapsac to get f f_optim_parameters = [handles.no_samp, handles.f_threshold]; [f,f_sq_errors, n_inliers,inlier_index] = torr_estimateF(handles.matches12, handles.m3, f_optim_parameters, 'mapsac'); disp('goodness of fit before non linear:') norm(f_sq_errors) handles.f = f; handles.inlier_matches = handles.matches12(inlier_index,:); handles.n_inliers = n_inliers; %first estimate F [f_nl,f_sq_errors] = torr_estimateF(handles.inlier_matches, handles.m3, [], 'non_linear',1,f); handles.f = f_nl; disp('goodness of fit after non linear:') norm(f_sq_errors) %finally display inliers clear_button_Callback(h, eventdata, handles, varargin); display_inliers(h, eventdata, handles, varargin); %we can now save the result set(handles.save_F_button, 'Enable', 'on'); set(handles.detect_corner_button, 'Enable', 'off'); set(handles.match_button, 'Enable', 'off'); set(handles.display_epipolar_button, 'Enable', 'on'); set(handles.display_epipolar_button2, 'Enable', 'on'); %set(handles.mapsac_plane_button, 'Enable', 'on'); set(handles.ImproveF_button, 'Enable', 'on'); set(handles.sfm_button, 'Enable', 'on'); % saving the GUI data guidata(handles.figure1, handles); % -------------------------------------------------------------------- function varargout = mapsac_parameters_button_Callback(h, eventdata, handles, varargin) pos_size = get(handles.figure1,'Position'); dlg_pos = [pos_size(1)+pos_size(3)/5 pos_size(2)+pos_size(4)/5]; f_param = torr_f_menu(handles, dlg_pos); handles.no_samp = f_param(1); handles.f_threshold = f_param(2); % saving the GUI data guidata(handles.figure1, handles); %-------------------------------------------------------------- %here we save all the stuff in corner file, match file and add some extras.... % -------------------------------------------------------------------- function varargout = save_F_button_Callback(h, eventdata, handles, varargin) [fname,pname] = uiputfile_name('*.Fmatches','Put F & inlying matches'); f = handles.f; inlier_matches = handles.inlier_matches; n_inliers = handles.n_inliers; n_matches = handles.n_matches; matches12 = handles.matches12; f = handles.f; f FID = fopen([pname fname],'w'); %save F stuff fprintf(FID,'%1.0f \n',n_inliers); fprintf(FID,'%12.8f \n', f); fprintf(FID,'%1.1f %1.1f %1.1f %1.1f \n',inlier_matches'); %save correlation matches fprintf(FID,'%1.0f \n',n_matches); fprintf(FID,'%1.1f %1.1f %1.1f %1.1f \n',matches12'); %now store original corners for good measure: n_corners = handles.n_corners; ccr1 = handles.ccr1; ccr2 = handles.ccr2; n_corners1 = handles.n_corners1; n_corners2 = handles.n_corners2; save_corners_to_file(n_corners1, n_corners2, ccr1, ccr2, FID); fclose(FID); % -------------------------------------------------------------------- function varargout = load_F_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.pushbutton28. [fname,pname] = uigetfile_name('*.fmatches','Load Match File'); if isempty(fname) return end %set(handles.mapsac_plane_button, 'Enable', 'on'); set(handles.mapsac_button, 'Enable', 'on'); set(handles.mapsac_parameters_button, 'Enable', 'on'); set(handles.save_F_button, 'Enable', 'on'); set(handles.ImproveF_button, 'Enable', 'on'); set(handles.sfm_button, 'Enable', 'on'); FID = fopen([pname fname]); %save F stuff n_inliers = fscanf(FID,'%f',1); f = fscanf(FID,'%f',[1 9]); inlier_matches = fscanf(FID,'%f %f %f %f',[4 n_inliers]); disp('fundamental matrix') handles.f = f handles.inlier_matches = inlier_matches'; handles.n_inliers = n_inliers; n_matches = fscanf(FID,'%f',1); handles.n_matches = n_matches; matches12 = fscanf(FID,'%f %f %f %f',[4 n_matches]); [n_corners1, n_corners2, ccr1, ccr2] = load_corners_from_file(FID); handles.n_corners1 = n_corners1; handles.n_corners2 = n_corners2; handles.ccr1 = ccr1'; handles.ccr2 = ccr2'; fclose(FID); handles.matches12 = matches12'; set(handles.save_corner_button, 'Enable', 'on'); set(handles.save_match_button, 'Enable', 'on'); set(handles.match_button, 'Enable', 'on'); set(handles.match_param_button, 'Enable', 'on'); set(handles.detect_corner_button, 'Enable', 'off'); set(handles.match_button, 'Enable', 'off'); set(handles.display_epipolar_button, 'Enable', 'on'); set(handles.display_epipolar_button2, 'Enable', 'on'); % Stub for Callback of the uicontrol handles.pushbutton28. set(handles.mapsac_button, 'Enable', 'on'); set(handles.mapsac_parameters_button, 'Enable', 'on'); %we can now save the result set(handles.save_F_button, 'Enable', 'on'); % saving the GUI data guidata(handles.figure1, handles); clear_button_Callback(h, eventdata, handles, varargin) %display_matches(h, eventdata, handles, varargin) %finally display inliers display_inliers(h, eventdata, handles, varargin); %%%---------------------------------------------------------------------------------- %%%%this is not 100% checked.... function varargout = display_epipolar_button_Callback(h, eventdata, handles, varargin) torr_display_epipolar(handles.f,handles.axes2,handles.axes3,handles.m3); %%%---------------------------------------------------------------------------------- function varargout = display_epipolar_button2_Callback(h, eventdata, handles, varargin) f = handles.f; %need to use the transpose of F for image 2--1 f = [f(1) f(4) f(7) f(2) f(5) f(8) f(3) f(6) f(9)]; torr_display_epipolar(f,handles.axes3,handles.axes2,handles.m3); %%%---------------------------------------------------------------------------------- % -------------------------------------------------------------------- function varargout = mapsac_plane_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.mapsac_plane_button. % Stub for Callback of the uicontrol handles.mapsac_button. %run mapsac to get f [f,f_sq_errors, n_inliers,inlier_index] = torr_mapsac_H(handles.matches12(:,1),handles.matches12(:,2),handles.matches12(:,3),handles.matches12(:,4), ... handles.n_matches, handles.m3, handles.no_samp, handles.f_threshold) handles.f = f; handles.inlier_matches = handles.matches12(inlier_index,:); handles.n_inliers = n_inliers; %finally display inliers clear_button_Callback(h, eventdata, handles, varargin); display_inliers(h, eventdata, handles, varargin); %we can now save the result set(handles.save_F_button, 'Enable', 'on'); set(handles.detect_corner_button, 'Enable', 'off'); set(handles.match_button, 'Enable', 'off'); set(handles.display_epipolar_button, 'Enable', 'on'); set(handles.display_epipolar_button2, 'Enable', 'on'); % saving the GUI data guidata(handles.figure1, handles); % -------------------------------------------------------------------- function varargout = ImproveF_button_Callback(h, eventdata, handles, varargin) % Stub for Callback of the uicontrol handles.ImproveF_button. %this function simply operates on the set of matches with no robustness %to be used with manual input etc... handles.m3 = 256; %first estimate F f = torr_estimateF(handles.matches12, handles.m3, [], 'lin+non_lin'); handles.f = f; %we can now save the result set(handles.save_F_button, 'Enable', 'on'); set(handles.detect_corner_button, 'Enable', 'off'); set(handles.match_button, 'Enable', 'off'); set(handles.display_epipolar_button, 'Enable', 'on'); set(handles.display_epipolar_button2, 'Enable', 'on'); %set(handles.mapsac_plane_button, 'Enable', 'on'); set(handles.ImproveF_button, 'Enable', 'on'); set(handles.sfm_button, 'Enable', 'on'); % saving the GUI data guidata(handles.figure1, handles); % -------------------------------------------------------------------- % -------------------------------------------------------------------- function varargout = sfm_button_Callback(h, eventdata, handles, varargin) %this function estalishes the frame, self calibrates and estimates X f = handles.f; nF = [[f(1) f(2) f(3)]; [f(4) f(5) f(6)];[f(7) f(8) f(9)]]; nx1 = handles.inlier_matches(:,1); ny1 = handles.inlier_matches(:,2); nx2 = handles.inlier_matches(:,3); ny2 = handles.inlier_matches(:,4); no_matches = length(nx1); m3 = handles.m3; %next self calibrate for focal length [focal_length, nE,C] = torr_self_calib_f(nF,handles.C); % disp('initial estimate of focal length') focal_length %now we have an Essential matrix we can establish the camera frame... [P1,P2,R,t,srot_axis,rot_angle,g] = torr_linear_EtoPX(nE,handles.inlier_matches,C,handles.m3); % %next convert the 6 parameters of g to a fundamental matrix % f2 = torr_g2F(g,C); [g,f] = torr_nonlinG(g ,nx1,ny1,nx2,ny2, length(nx1), handles.m3, C) rot_axis = torr_sphere2unit([g(2) g(3)]); t = torr_sphere2unit([g(5) g(6)]); rot_angle = g(4); disp('non_linear estimate of focal length') focal_length disp('rotation') R rot_axis rot_angle disp('translation') t %next correct the points so that they lie on the fundamental matrix [corrected_matches error2] = torr_correctx4F(f, nx1,ny1,nx2,ny2, no_matches, m3); %corrected matches should have zero error: e2 = torr_errf2(f, corrected_matches(:,1), corrected_matches(:,2), corrected_matches(:,3),corrected_matches(:,4), length(nx1), m3); disp('corrected match error is') norm(e2) %next we need to obtain P1 & P2 [P1, P2] = torr_g2FP(g,C); %now use P matrices and corrected matches to get structure: X = torr_triangulate(corrected_matches, m3, P1, P2); %note structure is upside down! %test reprojection error % rx1 = (P1 * X)'; % % rx1(:,1) = m3 * rx1(:,1) ./ rx1(:,3); % rx1(:,2) = m3 * rx1(:,2) ./ rx1(:,3); % % rx2 = P2 * X; inlier_index = torr_robust_chieral(X,P1,P2); disp('number of outliers from chierality:') no_matches - length(inlier_index) X = X(:,inlier_index); %flash up a new window and display the structure plus cameras: %invert = 1; % note becuase of row/column coordinate system of the image the X's are upside down so invert them prior % to display. X(2,:) = -X(2,:); torr_display_structure(X, P1, P2); X(2,:) = -X(2,:); handles.P1 = P1; handles.P2 = P2; handles.X = X; handles.inlier_matches = handles.inlier_matches(inlier_index,:); handles.focal_length = focal_length; handles.E = nE; handles.C = C; handles.f = f; handles.n_matches = no_matches; % saving the GUI data guidata(handles.figure1, handles); % -------------------------------------------------------------------- function varargout = sfm_parambutton_Callback(h, eventdata, handles, varargin) pos_size = get(handles.figure1,'Position'); dlg_pos = [pos_size(1)+pos_size(3)/5 pos_size(2)+pos_size(4)/5]; cal_param = torr_cal_menu(handles, dlg_pos); handles.focal_length = cal_param(1); handles.aspect_ratio = cal_param(2); handles.ppx = cal_param(3); handles.ppy = cal_param(4); %work out calibration matrix C = [ handles.aspect_ratio 0 handles.ppx; 0 1 handles.ppy; 0 0 1/handles.focal_length]; C handles.C = C; % saving the GUI data guidata(handles.figure1, handles); % -------------------------------------------------------------------- function varargout = initialize(handles) disp('this function isnt ready yet'); %phils atuff added, initialization %corner parameters handles.n_corners = 500; %max no of corners permitted/requested handles.n_corners1 = 0; %the actual number detected handles.n_corners2 = 0; handles.corner_sigma = 1.0; handles.corner_width = 3; %matchin parameters handles.max_disparity = 100; handles.match_half_size = 3; %F parameters: handles.no_samp = 500; % no of samples in the mapsac algorithm handles.f_threshold = 6.0; % f_threshold in the mapsac algorithm %informational variables handles.n_matches = 0; %how many matches have we dectected. %general parameters %debugt mode handles.debug = 1; handles.m3 = 256; %third homogeous pixel coordinate, chosen as 256 to help conditioning, see my thesis handles.pathname = ['C:\matlabR12\bin\']; %calibration matrix handles.focal_length = 3; %first guess, which is in units of m3 i.e %focal length in pixels is 3 * m3 handles.aspect_ratio = 1; handles.ppx = 0; handles.ppy = 0; %work out calibration matrix C = [a 0 handles.ppx; 0 1 handles.ppy; 0 0 1/handles.focal_length]; handles.C = C; if ~handles.debug helpdlg('Phil asks: "how ya diddling", first load some images') end set(handles.save_image1_button, 'Enable', 'off'); set(handles.save_image2_button, 'Enable', 'off'); set(handles.Save_Images_menu, 'Enable', 'off'); %for corners set(handles.detect_corner_button, 'Enable', 'off'); set(handles.save_corner_button, 'Enable', 'off'); set(handles.load_corner_button, 'Enable', 'off'); set(handles.corn_param_button, 'Enable', 'off'); %for correlation matches set(handles.match_button, 'Enable', 'off'); set(handles.match_param_button, 'Enable', 'off'); set(handles.manual_match_button, 'Enable', 'off'); set(handles.save_match_button, 'Enable', 'off'); set(handles.load_match_button, 'Enable', 'off'); %for F and correlation matches set(handles.mapsac_button, 'Enable', 'off'); set(handles.mapsac_parameters_button, 'Enable', 'off'); set(handles.save_F_button, 'Enable', 'off'); set(handles.display_epipolar_button, 'Enable', 'off'); set(handles.display_epipolar_button2, 'Enable', 'off'); %self calibrate set(handles.calibrate_button, 'Enable', 'on'); guidata(handles.figure1, handles); % -------------------------------------------------------------------- function varargout = epi_button_Callback(h, eventdata, handles, varargin) torr_disp_epip_geom(handles.f,handles.matches12,handles.axes2,handles.axes3,handles.m3); f = handles.f; f = [f(1) f(4) f(7) f(2) f(5) f(8) f(3) f(6) f(9)]; torr_disp_epip_geom(handles.f,handles.matches12,handles.axes3,handles.axes2,handles.m3); % --------------------------------------------------------------------