No BSD License  

Highlights from
Structure and Motion Toolkit in MATLAB

Structure and Motion Toolkit in MATLAB

by

 

04 Mar 2004 (Updated )

Structure and Motion Toolkit in MATLAB.

torr_tool(varargin)
%	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:
%| <SUBFUNCTION_NAME>(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:
%| <MFILENAME>('<SUBFUNCTION_NAME>', 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);



% --------------------------------------------------------------------







Contact us