Skip to content

Commit

Permalink
Make codes compatible for Linux (pull request by goodguykor)
Browse files Browse the repository at this point in the history
  • Loading branch information
sunglok committed Jul 19, 2017
1 parent 81d8264 commit fe40729
Show file tree
Hide file tree
Showing 13 changed files with 88 additions and 112 deletions.
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 2.6)
project(RTL)

set(RTL_OUTPUT_BIN_DIR ${RTL_BINARY_DIR}/bin)

make_directory(${RTL_OUTPUT_BIN_DIR})

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${RTL_OUTPUT_BIN_DIR}")

add_subdirectory(examples)
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
## RTL: RANSAC Template Library
_RANSAC Template Library (RTL)_ is an open-source robust regression library especially with RANSAC family.
RTL aims to provide fast, accurate, and easy ways to estimate any model parameters with data contaminated with outliers.
_RANSAC Template Library (RTL)_ is an open-source robust regression tool especially with RANSAC family.
RTL aims to provide fast, accurate, and easy ways to estimate any model parameters with data contaminated with outliers (incorrect data).
RTL includes recent RANSAC variants with their performance evaluation with several models with synthetic and real data.
RTL is written in generic programming style (template in C++) for its further applications with user-defined models.
RTL is distributed under [Simplified BSD License](http://opensource.org/licenses/BSD-2-Clause).

### What is RANSAC?
_Random sample consensus (RANSAC)_ is an iterative method to make the previous parameter estimators strong against outliers.
For example of line fitting, RANSAC enable to estimate a line parameter even though data points include incorrect point observations far from the line.
_RANdom SAmple Consensus (RANSAC)_ is an iterative method to make any parameter estimator strong against outliers.
For example of line fitting, RANSAC enable to estimate a line parameter even though data points include wrong point observations far from the true line.
RANSAC is composed of two steps, hypothesis generation and hypothesis evaluation.
It was original proposed by by Fischler and Bolles in 1981, but still utilized popularly to deal with outliers.
In the first step, RANSAC estimates a line (hypothesis) from randomly sampled point data.
In the second step, RANSAC counts the number of points which support the estimated line within the given threshold.
After several iterations of two steps, the final line can be obtained as a line who got the most supporters and inliers can determined as its supporters.
RANSAC was original proposed by Fischler and Bolles in 1981, but still utilized popularly to deal with outliers.

### Example
If a model estimator is defined in advance (e.g. LineEstimator), you can simply use RTL as follows.
Expand All @@ -35,7 +38,8 @@ Please refer a simple example, [ExampleMean.cpp](https://github.com/sunglok/rtl/
### Authors
* [Sunglok Choi](http://sites.google.com/site/sunglok/) (sunglok AT hanmail DOT net)
* Taemin Kim
* [Deok-Hwa Kim](http://rit.kaist.ac.kr/home/dhkim) (dhkim AT rit DOT kaist DOT ac DOT kr)
* Taemin Kim (luminans AT gmail DOT com)
### Reference
* Sunglok Choi, Taemin Kim, and Wonpil Yu, __Performance Evaluation of RANSAC Family__, in Proceedings of British Machine Vision Conference (BMVC), 2009 [PDF](https://sites.google.com/site/sunglok/files/Choi09_bmvc.pdf?attredirects=0)
Expand Down
15 changes: 15 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
include_directories(${CMAKE_SOURCE_DIR}/rtl)

if(WIN32)
set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -Ox -MP")
else()
set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -std=c++11 -O3 -fopenmp")
endif()

option(BUILD_EXAMPLE "Example Files" true)

if(BUILD_EXAMPLE)
add_executable ( ExampleMean ExampleMean.cpp )
add_executable ( ExampleLineFitting ExampleLineFitting.cpp )
add_executable ( EvaluateLineFitting EvaluateLineFitting.cpp )
endif()
10 changes: 5 additions & 5 deletions examples/EvaluateLineFitting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ bool RunRandomExp(const char* output, AlgoPtr algoPtr[], int algoNum, LineEstima
int main(void)
{
// Configure experiments
const Line CONFIG_MODEL_TRUTH (0.6, 0.8, -300);
const ExpVar CONFIG_EXP_DEFAULT ( 200, 0.6, 0.5);
const ExpVar CONFIG_EXP_MIN ( 100, 0.2, 0.1);
const ExpVar CONFIG_EXP_MAX (1000, 2.0, 0.9);
const ExpVar CONFIG_EXP_STEP ( 100, 0.2, 0.1);
const Line CONFIG_MODEL_TRUTH(0.6, 0.8, -300);
const ExpVar CONFIG_EXP_DEFAULT(200, 0.6, 0.5);
const ExpVar CONFIG_EXP_MIN(100, 0.2, 0.1);
const ExpVar CONFIG_EXP_MAX(1000, 2.0, 0.9);
const ExpVar CONFIG_EXP_STEP(100, 0.2, 0.1);
const int CONFIG_EXP_TRIAL = 1000;
const char* CONFIG_EXP_NAME1 = "LineRandom(DataNum).csv";
const char* CONFIG_EXP_NAME2 = "LineRandom(NoiseLevel).csv";
Expand Down
2 changes: 1 addition & 1 deletion examples/ExampleLineFitting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ int main(void)
// Determine inliers using the best model if necessary
vector<int> inliers = ransac.FindInliers(model, data, data.size());

// Print the result
// Print the result
cout << "- True Model: " << trueModel << endl;
cout << "- Found Model: " << model << " (Loss: " << loss << ")" << endl;
cout << "- The Number of Inliers: " << inliers.size() << " (N: " << data.size() << ")" << endl;
Expand Down
21 changes: 10 additions & 11 deletions examples/ExampleMean.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,39 @@
using namespace std;

// A mean calculator
class MeanEstimator : public RTL::Estimator<double, double, double*>
class MeanEstimator : public RTL::Estimator<double, double, vector<double> >
{
public:
// Calculate the mean of data at the sample indices
virtual Model ComputeModel(const Data& data, const set<int>& samples)
virtual double ComputeModel(const vector<double>& data, const set<int>& samples)
{
Model mean = 0;
double mean = 0;
for (auto itr = samples.begin(); itr != samples.end(); itr++) mean += data[*itr];
return mean / samples.size();
}

// Calculate error between the mean and given datum
virtual double ComputeError(const Model& mean, const Datum& datum) { return datum - mean; }
virtual double ComputeError(const double& mean, const double& datum) { return datum - mean; }
};

// The main function
int main(void)
{
// The given data with outliers
double data[] = { 2.5, 2.6, 2.7, 2.8, 2.9, 3, 3.1, 3.2, 100, 3.3, 3.4, 3.5 };
int n = sizeof(data) / sizeof(double);
vector<double> data = { 2.5, 2.6, 2.7, 2.8, 2.9, 3, 3.1, 3.2, 100, 3.3, 3.4, 3.5 };

// Find the best model using RANSAC
MeanEstimator estimator;
RTL::RANSAC<double, double, double*> ransac(&estimator);
RTL::RANSAC<double, double, vector<double> > ransac(&estimator);
double model;
double loss = ransac.FindBest(model, data, n, 1);
double loss = ransac.FindBest(model, data, data.size(), 1);

// Determine inliers using the best model if necessary
vector<int> inliers = ransac.FindInliers(model, data, n);
vector<int> inliers = ransac.FindInliers(model, data, data.size());

// Print the result
// Print the result
cout << "- Found Model: " << model << " (Loss: " << loss << ")" << endl;
cout << "- The Number of Inliers: " << inliers.size() << " (N: " << n << ")" << endl;
cout << "- The Number of Inliers: " << inliers.size() << " (N: " << data.size() << ")" << endl;

return 0;
}
16 changes: 2 additions & 14 deletions rtl/Base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,19 @@
namespace RTL
{

template <class ModelT, class DatumT, class DataT>
template <class Model, class Datum, class Data>
class Estimator
{
public:
typedef ModelT Model;

typedef DatumT Datum;

typedef DataT Data;

virtual Model ComputeModel(const Data& data, const std::set<int>& samples) = 0;

virtual double ComputeError(const Model& model, const Datum& datum) = 0;
};

template <class ModelT, class DatumT, class DataT>
template <class Model, class Datum, class Data>
class Observer
{
public:
typedef ModelT Model;

typedef DatumT Datum;

typedef DataT Data;

virtual Data GenerateData(const Model& model, int N, std::vector<int>& inliers, double noise = 0, double ratio = 1) = 0;
};

Expand Down
50 changes: 8 additions & 42 deletions rtl/Evaluator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@

#include "Base.hpp"
#include <algorithm>
#ifdef _WIN32
# include <windows.h>
#else
# include <sys/time.h>
#endif
#include <chrono>

class Score
{
Expand All @@ -23,16 +19,10 @@ class Score
int fn;
};

template <class ModelT, class DatumT, class DataT>
template <class Model, class Datum, class Data>
class Evaluator
{
public:
typedef ModelT Model;

typedef DatumT Datum;

typedef DataT Data;

Evaluator(RTL::Estimator<Model, Datum, Data>* estimator)
{
assert(estimator != NULL);
Expand Down Expand Up @@ -105,48 +95,24 @@ class StopWatch
public:
StopWatch()
{
#ifdef _WIN32
::QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
::QueryPerformanceCounter((LARGE_INTEGER*)&start);
#else
start.tv_sec = start.tv_usec = 0;
gettimeofday(&start, NULL);
#endif
Start();
}

bool Start(void)
{
#ifdef _WIN32
::QueryPerformanceCounter((LARGE_INTEGER*)&start);
start = std::chrono::high_resolution_clock::now();
return true;
#else
gettimeofday(&start, NULL);
#endif
}

double GetElapse(void)
{
#ifdef _WIN32
assert(freq.QuadPart != 0);
LARGE_INTEGER finish;
::QueryPerformanceCounter((LARGE_INTEGER*)&finish);
return (static_cast<double>(finish.QuadPart - start.QuadPart) / freq.QuadPart);
#else
struct timeval finish;
gettimeofday(&finish, NULL);
return (finish.tv_sec - start.tv_sec + static_cast<double>(finish.tv_usec - start.tv_usec) / 1000000);

#endif
std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
return static_cast<double>(time_span.count());
}

private:
#ifdef _WIN32
LARGE_INTEGER freq;

LARGE_INTEGER start;
#else
struct timeval start;
#endif
std::chrono::high_resolution_clock::time_point start;
};

#endif // End of '__RTL_EVALUATOR__'
4 changes: 2 additions & 2 deletions rtl/LMedS.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
namespace RTL
{

template <class ModelT, class DatumT, class DataT>
class LMedS : public RANSAC<ModelT, DatumT, DataT>
template <class Model, class Datum, class Data>
class LMedS : virtual public RANSAC<Model, Datum, Data>
{
public:
LMedS(Estimator<Model, Datum, Data>* estimator) : RANSAC<Model, Datum, Data>(estimator) { }
Expand Down
30 changes: 15 additions & 15 deletions rtl/Line.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Point
{
public:
Point() : x(0), y(0) { }

Point(double _x, double _y) : x(_x), y(_y) { }

friend std::ostream& operator<<(std::ostream& out, const Point& p) { return out << p.x << ", " << p.y; }
Expand All @@ -30,15 +30,15 @@ class Line
double a, b, c;
};

class LineEstimator : public RTL::Estimator<Line, Point, std::vector<Point> >
class LineEstimator : virtual public RTL::Estimator<Line, Point, std::vector<Point> >
{
public:
virtual Model ComputeModel(const Data& data, const std::set<int>& samples)
virtual Line ComputeModel(const std::vector<Point>& data, const std::set<int>& samples)
{
double meanX = 0, meanY = 0, meanXX = 0, meanYY = 0, meanXY = 0;
for (auto itr = samples.begin(); itr != samples.end(); itr++)
{
const Datum& p = data[*itr];
const Point& p = data[*itr];
meanX += p.x;
meanY += p.y;
meanXX += p.x * p.x;
Expand All @@ -51,11 +51,11 @@ class LineEstimator : public RTL::Estimator<Line, Point, std::vector<Point> >
meanXX /= M;
meanYY /= M;
meanXY /= M;
double a = meanXX - meanX*meanX;
double b = meanXY - meanX*meanY;
double d = meanYY - meanY*meanY;
double a = meanXX - meanX * meanX;
double b = meanXY - meanX * meanY;
double d = meanYY - meanY * meanY;

Model line;
Line line;
if (fabs(b) > DBL_EPSILON)
{
// Calculate the first eigen vector of A = [a, b; b, d]
Expand All @@ -76,29 +76,29 @@ class LineEstimator : public RTL::Estimator<Line, Point, std::vector<Point> >
return line;
}

virtual double ComputeError(const Model& line, const Datum& point)
virtual double ComputeError(const Line& line, const Point& point)
{
return line.a * point.x + line.b * point.y + line.c;
}
}; // End of 'LineEstimator'

class LineObserver : public RTL::Observer<Line, Point, std::vector<Point> >
class LineObserver : virtual public RTL::Observer<Line, Point, std::vector<Point> >
{
public:
LineObserver(Point _max = Point(640, 480), Point _min = Point(0, 0)) : RANGE_MAX(_max), RANGE_MIN(_min) { }

virtual Data GenerateData(const Model& line, int N, std::vector<int>& inliers, double noise = 0, double ratio = 1)
virtual std::vector<Point> GenerateData(const Line& line, int N, std::vector<int>& inliers, double noise = 0, double ratio = 1)
{
std::mt19937 generator;
std::uniform_real<double> uniform(0, 1);
std::uniform_real_distribution<double> uniform(0, 1);
std::normal_distribution<double> normal(0, 1);

Data data;
std::vector<Point> data;
if (fabs(line.b) > fabs(line.a))
{
for (int i = 0; i < N; i++)
{
Datum point;
Point point;
point.x = (RANGE_MAX.x - RANGE_MIN.x) * uniform(generator) + RANGE_MIN.x;
double vote = uniform(generator);
if (vote > ratio)
Expand All @@ -121,7 +121,7 @@ class LineObserver : public RTL::Observer<Line, Point, std::vector<Point> >
{
for (int i = 0; i < N; i++)
{
Datum point;
Point point;
point.y = (RANGE_MAX.y - RANGE_MIN.y) * uniform(generator) + RANGE_MIN.y;
double vote = uniform(generator);
if (vote > ratio)
Expand Down
10 changes: 5 additions & 5 deletions rtl/MLESAC.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
namespace RTL
{

template <class ModelT, class DatumT, class DataT>
class MLESAC : public MSAC<ModelT, DatumT, DataT>
template <class Model, class Datum, class Data>
class MLESAC : virtual public RANSAC<Model, Datum, Data>
{
public:
MLESAC(Estimator<Model, Datum, Data>* estimator) : MSAC<Model, Datum, Data>(estimator)
MLESAC(Estimator<Model, Datum, Data>* estimator) : RANSAC<Model, Datum, Data>(estimator)
{
dataError2 = NULL;
SetParamIterationEM();
Expand All @@ -32,7 +32,7 @@ class MLESAC : public MSAC<ModelT, DatumT, DataT>
protected:
virtual void Initialize(const Data& data, int N)
{
MSAC::Initialize(data, N);
RANSAC::Initialize(data, N);
dataError2 = new double[N];
assert(dataError2 != NULL);
double sigma = paramThreshold / paramSigmaScale;
Expand Down Expand Up @@ -86,7 +86,7 @@ class MLESAC : public MSAC<ModelT, DatumT, DataT>
delete [] dataError2;
dataError2 = NULL;
}
MSAC::Terminate(bestModel, data, N);
RANSAC::Terminate(bestModel, data, N);
}

int paramIterationEM;
Expand Down
Loading

0 comments on commit fe40729

Please sign in to comment.