Image Component Library (ICL)
|
00001 /******************************************************************** 00002 ** Image Component Library (ICL) ** 00003 ** ** 00004 ** Copyright (C) 2006-2013 CITEC, University of Bielefeld ** 00005 ** Neuroinformatics Group ** 00006 ** Website: www.iclcv.org and ** 00007 ** http://opensource.cit-ec.de/projects/icl ** 00008 ** ** 00009 ** File : ICLMath/src/ICLMath/RansacFitter.h ** 00010 ** Module : ICLMath ** 00011 ** Authors: Christof Elbrechter ** 00012 ** ** 00013 ** ** 00014 ** GNU LESSER GENERAL PUBLIC LICENSE ** 00015 ** This file may be used under the terms of the GNU Lesser General ** 00016 ** Public License version 3.0 as published by the ** 00017 ** ** 00018 ** Free Software Foundation and appearing in the file LICENSE.LGPL ** 00019 ** included in the packaging of this file. Please review the ** 00020 ** following information to ensure the license requirements will ** 00021 ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt ** 00022 ** ** 00023 ** The development of this software was supported by the ** 00024 ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** 00025 ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** 00026 ** Forschungsgemeinschaft (DFG) in the context of the German ** 00027 ** Excellence Initiative. ** 00028 ** ** 00029 ********************************************************************/ 00030 00031 #pragma once 00032 00033 #include <ICLUtils/CompatMacros.h> 00034 #include <ICLUtils/Function.h> 00035 #include <ICLUtils/Uncopyable.h> 00036 #include <ICLUtils/Random.h> 00037 #include <ICLMath/DynVector.h> 00038 #include <ICLMath/FixedVector.h> 00039 00040 namespace icl{ 00041 namespace math{ 00042 00043 00045 00061 template<class DataPoint=std::vector<float>, 00062 class Model=std::vector<float> > 00063 class RansacFitter{ 00064 public: 00066 typedef std::vector<DataPoint> DataSet; 00067 00069 typedef utils::Function<Model,const DataSet&> ModelFitting; 00070 00072 typedef utils::Function<icl64f,const Model&,const DataPoint&> PointError; 00073 00074 private: 00076 int m_minPointsForModel; 00077 00079 int m_iterations; 00080 00082 icl64f m_maxModelDistance; 00083 00085 int m_minClosePointsForGoodModel; 00086 00088 ModelFitting m_fitting; 00089 00091 PointError m_err; 00092 00094 icl64f m_minErrorExit; 00095 00096 public: 00098 struct Result{ 00100 icl64f error; 00101 00103 Model model; 00104 00106 00107 DataSet consensusSet; 00108 00110 int iterationCount; 00111 00113 bool found() const { return consensusSet.size(); } 00114 }; 00115 00116 private: 00118 Result m_result; 00119 00121 static inline bool find_in(const std::vector<int> &v, int i, int n){ 00122 return std::find(v.data(), v.data()+n, i) != v.data()+n; 00123 } 00124 00126 void find_random_consensus_set(DataSet &currConsensusSet, 00127 const DataSet &allPoints, 00128 std::vector<int> &usedIndices){ 00129 const int n = currConsensusSet.size(); 00130 utils::URandI r(allPoints.size()-1); 00131 00132 for(int i=0;i<n;++i){ 00133 do { usedIndices[i] = r; } while ( find_in(usedIndices, usedIndices[i], i-1) ); 00134 currConsensusSet[i] = allPoints[ usedIndices[i] ]; 00135 } 00136 } 00137 00138 public: 00140 RansacFitter(){} 00141 00143 00145 RansacFitter(int minPointsForModel, 00146 int iterations, 00147 ModelFitting fitting, 00148 PointError err, 00149 icl64f maxModelDistance, 00150 int minClosePointsForGoodModel, 00151 icl64f minErrorExit=0): 00152 m_minPointsForModel(minPointsForModel), 00153 m_iterations(iterations), 00154 m_maxModelDistance(maxModelDistance), 00155 m_minClosePointsForGoodModel(minClosePointsForGoodModel), 00156 m_fitting(fitting),m_err(err), 00157 m_minErrorExit(minErrorExit){ 00158 } 00159 00161 const Result &fit(const DataSet &allPoints){ 00162 m_result.model = Model(); 00163 m_result.consensusSet.clear(); 00164 m_result.error = utils::Range64f::limits().maxVal; 00165 m_result.iterationCount = 0; 00166 std::vector<DataPoint> consensusSet(m_minPointsForModel); 00167 std::vector<int> usedIndices(m_minPointsForModel); 00168 00169 int i = 0; 00170 for(i=0;i<m_iterations;++i){ 00171 consensusSet.resize(m_minPointsForModel); 00172 find_random_consensus_set(consensusSet, allPoints, usedIndices); 00173 00174 Model model = m_fitting(consensusSet); 00175 for(int j=0;j<(int)allPoints.size();++j){ 00176 if(find_in(usedIndices, j, usedIndices.size())) continue; 00177 if(m_err(model, allPoints[j]) < m_maxModelDistance){ 00178 consensusSet.push_back(allPoints[j]); 00179 } 00180 } 00181 00182 if((int)consensusSet.size() >= m_minClosePointsForGoodModel){ 00183 model = m_fitting(consensusSet); 00184 double error = 0; 00185 for(unsigned int j=0;j<consensusSet.size();++j){ 00186 error += m_err(model, consensusSet[j]); 00187 } 00188 error /= consensusSet.size(); 00189 00190 if(error < m_result.error){ 00191 m_result.error = error; 00192 m_result.model = model; 00193 m_result.consensusSet = consensusSet; 00194 if(m_result.error < m_minErrorExit){ 00195 m_result.iterationCount = i; 00196 return m_result; 00197 } 00198 } 00199 } 00200 } 00201 m_result.iterationCount = i; 00202 return m_result; 00203 } 00204 }; 00205 } // namespace math 00206 } 00207