diff --git a/.gitignore b/.gitignore index 3ac5a5c..68a4499 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ - -/build/MSVC9/EvaluateLineFitting/Debug -/build/MSVC9/ExampleLineFitting/Debug \ No newline at end of file +Debug +Release +ipch +*.exe +*.dll +*.ilk +*.pdb +*.aps +*.suo +*.sdf diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..986ea74 --- /dev/null +++ b/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2007, Sunglok Choi +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. diff --git a/README.md b/README.md index c54ea75..f84f1fa 100644 --- a/README.md +++ b/README.md @@ -1 +1,22 @@ -## RTL: RANSAC Template Library for C++ +## RTL: RANSAC Template Library +_RANSAC Template Library_ is an open-source library for RANSAC-based robust regression. +It is written in generic programming style with C++ and distributed under [Simplified BSD License](http://opensource.org/licenses/BSD-2-Clause). + +### Example + +### Features +* __Robust Regression__: RANSAC, LMedS, MSAC, MLESAC +* __Example Models__: Line + * __Synthetic Data Generation__: Line + +### Authors +* [Sunglok Choi](http://sites.google.com/site/sunglok/) (sunglok AT hanmail DOT net) +* Taemin Kim + +### 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) + +### Acknowledgement +The authors thank the following contributors and projects. + +* Junho Lee: He contributed LMedS and found several bugs. diff --git a/src/EvaluatorPlot.m b/bin/EvaluatorPlot.m similarity index 100% rename from src/EvaluatorPlot.m rename to bin/EvaluatorPlot.m diff --git a/src/LinePlot.m b/bin/LinePlot.m similarity index 100% rename from src/LinePlot.m rename to bin/LinePlot.m diff --git a/build/MSVC9/EvaluateLineFitting/EvaluateLineFitting.vcproj b/build/MSVC9/EvaluateLineFitting/EvaluateLineFitting.vcproj deleted file mode 100644 index c6ebf15..0000000 --- a/build/MSVC9/EvaluateLineFitting/EvaluateLineFitting.vcproj +++ /dev/null @@ -1,213 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/MSVC9/ExampleLineFitting/ExampleLineFitting.vcproj b/build/MSVC9/ExampleLineFitting/ExampleLineFitting.vcproj deleted file mode 100644 index 18e9bce..0000000 --- a/build/MSVC9/ExampleLineFitting/ExampleLineFitting.vcproj +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/MSVC9/RTL.sln b/build/MSVC9/RTL.sln deleted file mode 100644 index dee7656..0000000 --- a/build/MSVC9/RTL.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExampleLineFitting", "ExampleLineFitting\ExampleLineFitting.vcproj", "{C6DAC20C-B706-4882-B112-8E336FB24FE7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EvaluteLineFitting", "EvaluateLineFitting\EvaluateLineFitting.vcproj", "{0C296CBC-4B1B-4181-804E-7D4542261748}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C6DAC20C-B706-4882-B112-8E336FB24FE7}.Debug|Win32.ActiveCfg = Debug|Win32 - {C6DAC20C-B706-4882-B112-8E336FB24FE7}.Debug|Win32.Build.0 = Debug|Win32 - {C6DAC20C-B706-4882-B112-8E336FB24FE7}.Release|Win32.ActiveCfg = Release|Win32 - {C6DAC20C-B706-4882-B112-8E336FB24FE7}.Release|Win32.Build.0 = Release|Win32 - {0C296CBC-4B1B-4181-804E-7D4542261748}.Debug|Win32.ActiveCfg = Debug|Win32 - {0C296CBC-4B1B-4181-804E-7D4542261748}.Debug|Win32.Build.0 = Debug|Win32 - {0C296CBC-4B1B-4181-804E-7D4542261748}.Release|Win32.ActiveCfg = Release|Win32 - {0C296CBC-4B1B-4181-804E-7D4542261748}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/build/msvs/EvaluateLineFitting/EvaluateLineFitting.vcxproj b/build/msvs/EvaluateLineFitting/EvaluateLineFitting.vcxproj new file mode 100644 index 0000000..4b26dc6 --- /dev/null +++ b/build/msvs/EvaluateLineFitting/EvaluateLineFitting.vcxproj @@ -0,0 +1,90 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {6FD9D438-A0B5-4606-B56F-DD76E952740C} + Win32Proj + EvaluateLineFitting + + + + Application + true + v120 + Unicode + + + Application + false + v120 + true + Unicode + + + + + + + + + + + + + true + ..\..\..\bin\ + + + false + ..\..\..\bin\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + ../../../src;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + ../../../src;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/build/msvs/EvaluateLineFitting/EvaluateLineFitting.vcxproj.filters b/build/msvs/EvaluateLineFitting/EvaluateLineFitting.vcxproj.filters new file mode 100644 index 0000000..5c0e54a --- /dev/null +++ b/build/msvs/EvaluateLineFitting/EvaluateLineFitting.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + diff --git a/build/msvs/EvaluateLineFitting/EvaluateLineFitting.vcxproj.user b/build/msvs/EvaluateLineFitting/EvaluateLineFitting.vcxproj.user new file mode 100644 index 0000000..c1193f9 --- /dev/null +++ b/build/msvs/EvaluateLineFitting/EvaluateLineFitting.vcxproj.user @@ -0,0 +1,11 @@ + + + + $(OutDir) + WindowsLocalDebugger + + + $(OutDir) + WindowsLocalDebugger + + \ No newline at end of file diff --git a/build/msvs/ExampleLineFitting/ExampleLineFitting.vcxproj b/build/msvs/ExampleLineFitting/ExampleLineFitting.vcxproj new file mode 100644 index 0000000..5d9ad02 --- /dev/null +++ b/build/msvs/ExampleLineFitting/ExampleLineFitting.vcxproj @@ -0,0 +1,90 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {8ACE42D9-0F72-471F-94E8-E252BB55C0C0} + Win32Proj + ExampleLineFitting + + + + Application + true + v120 + Unicode + + + Application + false + v120 + true + Unicode + + + + + + + + + + + + + true + ..\..\..\bin\ + + + false + ..\..\..\bin\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + ../../../src;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + ../../../src;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/build/msvs/ExampleLineFitting/ExampleLineFitting.vcxproj.filters b/build/msvs/ExampleLineFitting/ExampleLineFitting.vcxproj.filters new file mode 100644 index 0000000..75cb056 --- /dev/null +++ b/build/msvs/ExampleLineFitting/ExampleLineFitting.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/build/msvs/ExampleLineFitting/ExampleLineFitting.vcxproj.user b/build/msvs/ExampleLineFitting/ExampleLineFitting.vcxproj.user new file mode 100644 index 0000000..c1193f9 --- /dev/null +++ b/build/msvs/ExampleLineFitting/ExampleLineFitting.vcxproj.user @@ -0,0 +1,11 @@ + + + + $(OutDir) + WindowsLocalDebugger + + + $(OutDir) + WindowsLocalDebugger + + \ No newline at end of file diff --git a/build/msvs/RTL.sln b/build/msvs/RTL.sln new file mode 100644 index 0000000..5134f68 --- /dev/null +++ b/build/msvs/RTL.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExampleLineFitting", "ExampleLineFitting\ExampleLineFitting.vcxproj", "{8ACE42D9-0F72-471F-94E8-E252BB55C0C0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EvaluateLineFitting", "EvaluateLineFitting\EvaluateLineFitting.vcxproj", "{6FD9D438-A0B5-4606-B56F-DD76E952740C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8ACE42D9-0F72-471F-94E8-E252BB55C0C0}.Debug|Win32.ActiveCfg = Debug|Win32 + {8ACE42D9-0F72-471F-94E8-E252BB55C0C0}.Debug|Win32.Build.0 = Debug|Win32 + {8ACE42D9-0F72-471F-94E8-E252BB55C0C0}.Release|Win32.ActiveCfg = Release|Win32 + {8ACE42D9-0F72-471F-94E8-E252BB55C0C0}.Release|Win32.Build.0 = Release|Win32 + {6FD9D438-A0B5-4606-B56F-DD76E952740C}.Debug|Win32.ActiveCfg = Debug|Win32 + {6FD9D438-A0B5-4606-B56F-DD76E952740C}.Debug|Win32.Build.0 = Debug|Win32 + {6FD9D438-A0B5-4606-B56F-DD76E952740C}.Release|Win32.ActiveCfg = Release|Win32 + {6FD9D438-A0B5-4606-B56F-DD76E952740C}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/examples/EvaluateLineFitting.cpp b/examples/EvaluateLineFitting.cpp index 7d7e3b2..4ccd47e 100644 --- a/examples/EvaluateLineFitting.cpp +++ b/examples/EvaluateLineFitting.cpp @@ -1,10 +1,6 @@ #include #include -#include "RANSAC.hpp" -#include "MSAC.hpp" -#include "MLESAC.hpp" -#include "Line.hpp" -#include "Evaluator.hpp" +#include "RTL.hpp" class ExpVar { diff --git a/examples/ExampleLineFitting.cpp b/examples/ExampleLineFitting.cpp index 9244aab..bf3b841 100644 --- a/examples/ExampleLineFitting.cpp +++ b/examples/ExampleLineFitting.cpp @@ -1,7 +1,6 @@ #include #include -#include "Line.hpp" -#include "RANSAC.hpp" +#include "RTL.hpp" // The main function int main(void) @@ -11,7 +10,7 @@ int main(void) std::vector data; std::vector trueInliers; Line trueModel(0.6, -0.8, 1); - if (!observer.GenerateData(data, trueInliers, trueModel, 100, 0.1, 0.5)) return -1; + if (!observer.GenerateData(data, trueInliers, trueModel, 100, 0.1, 0.6)) return -1; // Find the best model using RANSAC LineEstimator estimator; @@ -43,7 +42,7 @@ int main(void) std::cout << std::endl; } - std::cout.flags(original_flags); //6 + std::cout.flags(original_flags); // Print the result std::cout << "- True Model: " << trueModel << std::endl; diff --git a/src/Evaluator.hpp b/src/Evaluator.hpp index 1822e80..2b3dd83 100644 --- a/src/Evaluator.hpp +++ b/src/Evaluator.hpp @@ -5,6 +5,8 @@ #include #ifdef _WIN32 # include +#else +# include #endif class Score @@ -105,28 +107,48 @@ 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 } bool Start(void) { +#ifdef _WIN32 ::QueryPerformanceCounter((LARGE_INTEGER*)&start); 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(finish.QuadPart - start.QuadPart) / freq.QuadPart); +#else + struct timeval finish; + gettimeofday(&finish, NULL); + return (finish.tv_sec - start.tv_sec + static_cast(finish.tv_usec - start.tv_usec) / 1000000); + +#endif } private: +#ifdef _WIN32 LARGE_INTEGER freq; LARGE_INTEGER start; +#else + struct timeval start; +#endif }; #endif // End of '__RTL_EVALUATOR__' diff --git a/src/LMedS.hpp b/src/LMedS.hpp new file mode 100644 index 0000000..df6556b --- /dev/null +++ b/src/LMedS.hpp @@ -0,0 +1,28 @@ +#ifndef __RTL_LMEDS__ +#define __RTL_LMEDS__ + +#include "RANSAC.hpp" + +namespace RTL +{ + +template +class LMedS : public RANSAC +{ +public: + LMedS(Estimator* estimator) : RANSAC(estimator) { } + +protected: + virtual inline double EvaluateModel(const Model& model, const Data& data, int N) + { + std::vector errors(N); + for (int i = 0; i < N; i++) + errors[i] = toolEstimator->ComputeError(model, data[i]); + std::nth_element(errors.begin(), errors.begin() + N / 2, errors.end()); + return errors[N / 2]; + } +}; + +} // End of 'RTL' + +#endif // End of '__RTL_LMEDS__' diff --git a/src/Line.hpp b/src/Line.hpp index 8307b33..d36dd3e 100644 --- a/src/Line.hpp +++ b/src/Line.hpp @@ -105,12 +105,12 @@ class LineObserver : public RTL::Observer > for (int i = 0; i < N; i++) { Datum datum; - datum.x = (RANGE_MAX.x - RANGE_MIN.x) * uniform(generator) - RANGE_MIN.x; + datum.x = (RANGE_MAX.x - RANGE_MIN.x) * uniform(generator) + RANGE_MIN.x; double vote = uniform(generator); if (vote > ratio) { // Generate an outlier - datum.y = (RANGE_MAX.y - RANGE_MIN.y) * uniform(generator) - RANGE_MIN.y; + datum.y = (RANGE_MAX.y - RANGE_MIN.y) * uniform(generator) + RANGE_MIN.y; } else { @@ -128,12 +128,12 @@ class LineObserver : public RTL::Observer > for (int i = 0; i < N; i++) { Datum datum; - datum.y = (RANGE_MAX.y - RANGE_MIN.y) * uniform(generator) - RANGE_MIN.y; + datum.y = (RANGE_MAX.y - RANGE_MIN.y) * uniform(generator) + RANGE_MIN.y; double vote = uniform(generator); if (vote > ratio) { // Generate an outlier - datum.x = (RANGE_MAX.x - RANGE_MIN.x) * uniform(generator) - RANGE_MIN.x; + datum.x = (RANGE_MAX.x - RANGE_MIN.x) * uniform(generator) + RANGE_MIN.x; } else { @@ -160,12 +160,12 @@ class LineObserver : public RTL::Observer > for (int i = 0; i < N; i++) { Datum datum; - datum.x = (RANGE_MAX.x - RANGE_MIN.x) * uniform(generator) - RANGE_MIN.x; + datum.x = (RANGE_MAX.x - RANGE_MIN.x) * uniform(generator) + RANGE_MIN.x; double vote = uniform(generator); if (vote > ratio) { // Generate an outlier - datum.y = (RANGE_MAX.y - RANGE_MIN.y) * uniform(generator) - RANGE_MIN.y; + datum.y = (RANGE_MAX.y - RANGE_MIN.y) * uniform(generator) + RANGE_MIN.y; inliers.push_back(false); } else @@ -184,12 +184,12 @@ class LineObserver : public RTL::Observer > for (int i = 0; i < N; i++) { Datum datum; - datum.y = (RANGE_MAX.y - RANGE_MIN.y) * uniform(generator) - RANGE_MIN.y; + datum.y = (RANGE_MAX.y - RANGE_MIN.y) * uniform(generator) + RANGE_MIN.y; double vote = uniform(generator); if (vote > ratio) { // Generate an outlier - datum.x = (RANGE_MAX.x - RANGE_MIN.x) * uniform(generator) - RANGE_MIN.x; + datum.x = (RANGE_MAX.x - RANGE_MIN.x) * uniform(generator) + RANGE_MIN.x; inliers.push_back(false); } else diff --git a/src/MSAC.hpp b/src/MSAC.hpp index 4ee733a..3f6c00b 100644 --- a/src/MSAC.hpp +++ b/src/MSAC.hpp @@ -10,7 +10,7 @@ template class MSAC : public RANSAC { public: - MSAC(Estimator* estimator): RANSAC(estimator) { } + MSAC(Estimator* estimator) : RANSAC(estimator) { } protected: virtual inline double EvaluateModel(const Model& model, const Data& data, int N) diff --git a/src/RANSAC.hpp b/src/RANSAC.hpp index b6ffa8e..9252293 100644 --- a/src/RANSAC.hpp +++ b/src/RANSAC.hpp @@ -54,13 +54,13 @@ class RANSAC virtual inline bool UpdateBest(Model& bestModel, double& bestCost, const Model& model, double cost); - virtual inline void Initialize(const Data& data, int N) { toolUniform = std::tr1::uniform_int(0, N - 1); } + virtual inline void Initialize(const Data& data, int N) { toolUniform = std::uniform_int(0, N - 1); } virtual inline void Terminate(const Data& data, int N, const Model& bestModel) { } - std::tr1::mt19937 toolGenerator; + std::mt19937 toolGenerator; - std::tr1::uniform_int toolUniform; + std::uniform_int toolUniform; Estimator* toolEstimator; @@ -126,9 +126,9 @@ double RANSAC::FindBest(Model& best, const Data& d // 2. Evaluate the hypotheses for (int i = 0; i < num; i++) { - double modelloss = EvaluateModel(models[i], data, N); - if (modelloss < bestloss) - if (!UpdateBest(best, bestloss, models[i], modelloss)) + double loss = EvaluateModel(models[i], data, N); + if (loss < bestloss) + if (!UpdateBest(best, bestloss, models[i], loss)) goto RANSAC_FIND_BEST_EXIT; } } diff --git a/src/RTL.hpp b/src/RTL.hpp new file mode 100644 index 0000000..834f052 --- /dev/null +++ b/src/RTL.hpp @@ -0,0 +1,14 @@ +#ifndef __RTL__ +#define __RTL__ + +#include "Base.hpp" +#include "RANSAC.hpp" +#include "LMedS.hpp" +#include "MSAC.hpp" +#include "MLESAC.hpp" + +#include "Evaluator.hpp" + +#include "Line.hpp" + +#endif // End of '__RTL__'