Monday, December 19, 2011

Robust Nonlinear Fitting by RANSAC (Outlier Tolerent Nonlinear Regression)

Robust Nonlinear Optimization MATLAB Code Download [File->Download]

Please have a look in RANSAC_4_Nonlinear.m This code is not heavily tested. Therefore, please be warned! 

All credit goes to the RANSAC toolbox creator! I just tested it for a simple nonlinear function. 

Contents

%
% Objective: RANSAC for Robust Nonlinear Model Estimation
% Requirements: Optimization Toolbox (I am sorry, but its possible to modify the code to remove this dependency!)
% Important Acknowledgement: This RANSAC code is based on the RANSAC Toolbox [1][2]
% Thanks to the author for sharing but offcourse I do not take any
% responsibility neither for my or anyone else code! :-)
% --------------------------------------------------
% ACKNOWLEGEMENT:
%---------------------------------------------------
% [1] http://www.mathworks.com/matlabcentral/linkexchange/links/1814-ransac-toolbox
% [2] http://vision.ece.ucsb.edu/~zuliani/Research/RANSAC/RANSAC.shtml

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

%---------------------------------------------------
% Input:
%---------------------------------------------------
% This simple script will try to fit the following nonlinear model
% Y=offset+gain*(X.^gamma); The equation is formally defined in the
% function titled "mygogcurve"
% Here, X is the independent variable and saved in the first row of matrix "xdataydata"
% And Y is the dependent variable and saved in the second row of matrix
% titled "xdataydata". Our Objective is to find the 3 parameters (offset,gain and gamma respectively)

% User defined functions

% estimate_gog_line: This function is used by main RANSAC.m in two ways.
% First, its used to compute k, where k means minimum number of data
% required to estimate the model. Here, I understand that we need at least 3
% points to estimate my nonlinear model. But to capture the nonlinearity, I have forcefully demands at
% least 5% data to start the model. See the function code to see the detail.

% residual_error_gog_line: this function returns squared error(E) and degrees of freedom(d for dof)
% Since, we are searching for 3 parameters dof will be k-3. Squared error
% is computed by fit=Theta(1)*(X(1,:).^Theta(2))+Theta(3); E=(fit-(X(2,:))).^2;

%---------------------------------------------------
% Output:
%---------------------------------------------------
% Estimated parameters in matrix "parameter_hat" (offset,gain and gamma respectively)
% --------------------------------------------------
% SEE ALSO:
%---------------------------------------------------

% Nonlinear model part is written by:
% SHEIKH FARIDUL Hasan
% hasan.sheikh.faridul@univ-st-etienne.fr
% Hasan.Sheikh-Faridul@technicolor.com
% https://sites.google.com/site/infofaridulhasan/

Clearing and loading fresh data

close all
clear all
% clc
tic

load RGB_im2_im2

xdata=RGB_ref(:,1)'; % You may test xdata=RGB_ref(:,2)'; with ydata=RGB_test(:,2)'; OR xdata=RGB_ref(:,3)'; with ydata=RGB_test(:,3)';
ydata=RGB_test(:,1)';
xdataydata=[xdata; ydata];

setting RANSAC options

options.epsilon = 1e-6;
options.P_inlier = 0.95;
options.sigma = 1;
options.est_fun = @estimate_gog_line;
options.man_fun = @residual_error_gog_line;
options.mode = 'MSAC';
options.Ps = [];
options.notify_iters = [];
options.min_iters = 50;
options.fix_seed = false;
options.reestimate = true;
options.stabilize = false;
options.max_iters=100;

Running RANSAC

[results, options] = RANSAC(xdataydata, options);
Starting RANSAC
Minimal sample set dimension = 16
Squared noise threshold = 22.708231, (assuming Gaussian noise, for sigma = 1.000000)
Iteration =     1/       37. Inliers =    313/   336 (rank is r = -3.65524372)
Iteration =     2/       16. Inliers =    325/   336 (rank is r = -1.64444872)
Iteration =    10/       16. Inliers =    325/   336 (rank is r = -1.56384809)
Iteration =    24/       16. Inliers =    325/   336 (rank is r = -1.56014290)
Iteration =    28/       16. Inliers =    325/   336 (rank is r = -1.54867447)
Iteration =    45/       16. Inliers =    325/   336 (rank is r = -1.54532717)
Restimating the parameter vector... Done
Final number of inliers = 325/336
Converged in 51 iterations (0.898319 seconds)

GOG Parameter estimation from Inliers using levenberg-marquardt algorithm

ind = results.CS;

options_myfit=optimset('Algorithm',{'levenberg-marquardt',.005});
[parameter_hat,resnorm,residual,exitflag,output,lambda,jacobian] = lsqnonlin(@mygogcurve,[0;1;1],[],[],options_myfit,xdataydata(1, ind),xdataydata(2, ind));

toc
Local minimum found.

Optimization completed because the size of the gradient is less than
the default value of the function tolerance.



Elapsed time is 1.054063 seconds.

Results Visualization

figure;
hold on
plot(xdataydata(1, ind),xdataydata(2, ind), '.g')
plot(xdataydata(1, ~ind), xdataydata(2, ~ind), '.r')
plot([1:255],parameter_hat(1)+parameter_hat(2)*([1:255].^parameter_hat(3)),'b')
legend('Inliers', 'Outliers','LM-fit from inliers')

xlabel('x-reference color')
ylabel('y-test color')
title('RANSAC outlier detection and GOG Param by LM estimation')

Conclusion: Will be completed later 

5 comments:

  1. Dear Hasan,

    I am very interested to use your ransac algorithm implemented for matlab.
    I wish to test it as a pre-processing step to provide a reference data for kNN based growing-stock volume estimation by means of remote sensing.
    I downloaded the toolbox provided on your blog and started a first try with the test-data you provided.
    However, something seems not to work and I have no more idea what is the reason. I am using matlab (version 2008b), this code was written for an older version, I suppose. So might that be the reason.
    The error it gives me, after I insert the command
    [results, options] = RANSAC(xdataydata, options);
    is as following:

    Starting RANSACWarning: The option 'Algorithm' is an Optimization Toolbox option and is not
    used by any MATLAB functions. This option will be ignored and not included
    in the options returned by OPTIMSET. Please change your code to not use
    this option as it will error in a future release.
    > In optimset at 196
    In estimate_gog_line at 54
    In RANSAC at 229
    ??? Error using ==> minus
    Matrix dimensions must agree.

    Error in ==> lsqncommon at 43
    if min(min(u-xstart),min(xstart-l)) < 0

    Error in ==> lsqcurvefit at 186
    [x,Resnorm,FVAL,EXITFLAG,OUTPUT,LAMBDA,JACOB] = ...

    Error in ==> estimate_gog_line at 55
    [gog] = lsqcurvefit(@mygogfunc,[1;1;0],X(1,:),X(2, :),[],[],options_myfit);

    Error in ==> RANSAC at 229

    I hope, maybe you can help me with my problem.

    Sincerly yours,
    Sascha

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Dear Sascha,
    Could you please run(or debug step by step) RANSAC_4_Nonlinear.m (inside robust_nonlinear_optimization folder) and check whether it works or not?

    Please note that you will need optimization toolbox to run this code. You may run the command "ver"(without comma) to check whether you have optimization toolbox available in your system.

    I did not clearly understand what kind of regression will you need? Could you please explain your problem more precisely so that we may discuss.

    ReplyDelete
  4. Dear Hasan,

    thank you very much for the fast reply!
    I want to use a 2nd order polynomial regression.
    I checked out the matlab version, the optimization toolbox is available, but it seems like I don't have a license for optimization toolbox.
    Unfortunately, this week there will be nobody here to ask for the license key.
    However, I append the error message for you when the code stops running (it stops after the command

    "[results, options] = RANSAC(xdataydata, options);"

    For me, it seems like some matrix dimensions do not match, as the message tells:

    ??? Error using ==> minus
    Matrix dimensions must agree.

    Error in ==> lsqncommon at 43
    if min(min(u-xstart),min(xstart-l)) < 0

    Error in ==> lsqcurvefit at 186
    [x,Resnorm,FVAL,EXITFLAG,OUTPUT,LAMBDA,JACOB] = ...

    Error in ==> estimate_gog_line at 55
    [gog] = lsqcurvefit(@mygogfunc,[1;1;0],X(1,:),X(2, :),[],[],options_myfit);

    Error in ==> RANSAC at 229


    Error in ==> RANSAC_4_Nonlinear at 82
    [results, options] = RANSAC(xdataydata, options);

    Well, I try to install the licence key for optimization toolbox next week and give more feedback.

    Thanks and kind regards!

    ReplyDelete
  5. Hello Sascha,
    I think in your case, nlinfit from statistics toolbox will be more appropriate than using this modified version of RANSAC. Let me give an example (based upon matlab help page of nlinfit)

    http://machinethatsees.blogspot.co.uk/2012/09/robust-nonlinear-regression-with.html

    Please plot your data and see what kind of outliers are there. It will help you to decide which option to pick in "opts.RobustWgtFun=?"

    ReplyDelete

Please ask if anything is not clear enough..........