Learn-to-Compress / src / RANSAC.cpp
RANSAC.cpp
Raw
#include "../headers/RANSAC.h"
#include <cstring>
#include <math.h>
#include <algorithm>

RANSAC::RANSAC()
  :probability_(0.99), max_iterations_ (10)
{

}

int RANSAC::compute(lr& mylr, double x[], double y[],int numbers,int num_for_estimate,bool *choose)
{

  int num_data = numbers;

  int iterations = 0;  
  double k = 100;  


  double log_probability  = log (1.0 - probability_);
  double one_over_indices = 1.0 / static_cast<double> (num_data);
  
  

  short *best_votes = new short[num_data];
  short *cur_votes = new short[num_data]; 

  SubSetIndexComparator sub_set_index_comparator(num_for_estimate);
  std::set<int *, SubSetIndexComparator > chosen_sub_sets(sub_set_index_comparator);  


  int* cur_inti_sub_set_indexs = NULL;
  

  int best_model_num = -1;  
  int maybe_inliers_num = 0;  
  std::vector<double> maybe_model;  

  std::vector<int> shuffled_indices(num_data);

  while (iterations < k)
  {
      
      maybe_inliers_num = 0;
      cur_inti_sub_set_indexs = new int[num_for_estimate];
          

      maybe_model.clear();
    
      for (int i=0;i < (int)shuffled_indices.size(); i++)
      {
        shuffled_indices[i]=i;
      }

      int max_index = num_data-1;
      for (int i=0; i<num_for_estimate; i++)
      {
        std::swap(shuffled_indices[i], shuffled_indices[i + rand() % (numbers - i)]);
      }
    
      memset(cur_votes, 0, num_data*sizeof(short));

      for (int i=0; i<num_for_estimate; i++)
      {
        cur_inti_sub_set_indexs[i] = shuffled_indices[i];
        cur_votes[shuffled_indices[i]] = 1;
      }
      maybe_inliers_num = num_for_estimate;


      std::pair< std::set<int *, SubSetIndexComparator >::iterator, bool > res = chosen_sub_sets.insert(cur_inti_sub_set_indexs);

      if (res.second)
      {

        std::vector<double> tmpx;
        std::vector<double> tmpy;
        for (int i=0; i<num_for_estimate; i++)
        {
          tmpx.emplace_back(x[cur_inti_sub_set_indexs[i]]);
          tmpy.emplace_back(y[cur_inti_sub_set_indexs[i]]);
        }


        mylr.caltheta(tmpx,tmpy,num_for_estimate);

        for(int i=0; i<num_data; i++)
        {
          if(0 == cur_votes[i] && 
            mylr.agree(x[i],y[i]))
          {
            cur_votes[i] = 1;
            maybe_inliers_num++;          
          }
        }

        if (maybe_inliers_num > best_model_num)
        {
          best_model_num = maybe_inliers_num;
          memcpy(best_votes, cur_votes, num_data*sizeof(short));
        }

      //k=log(1-p)/log(1-pow(w,n))
        double w = static_cast<double> (best_model_num) * one_over_indices;
        double p_no_outliers = 1.0 - std::pow(w, static_cast<double> (maybe_inliers_num));
        if(abs(p_no_outliers-1.0)<std::numeric_limits<double>::epsilon ()){
          break;
        }
        p_no_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_no_outliers);       // Avoid division by -Inf
        p_no_outliers = (std::min) (1.0 - std::numeric_limits<double>::epsilon (), p_no_outliers);   // Avoid division by 0.
        k = log_probability / log(p_no_outliers);
      //std::cout<<"log_probability: "<<log_probability<<" log p_no_outliers: "<<p_no_outliers<<" k: "<<k<<" w: "<<w<<"inlier: "<<maybe_inliers_num<<std::endl;
      }
      else
      {
        delete [] cur_inti_sub_set_indexs;
        //--iterations;  
      }

      ++iterations;
    }

  std::set<int *, SubSetIndexComparator >::iterator it = chosen_sub_sets.begin();
  std::set<int *, SubSetIndexComparator >::iterator chosenSubSetsEnd = chosen_sub_sets.end();
  while(it!=chosenSubSetsEnd) {
    delete [] (*it);
    it++;
  }
  chosen_sub_sets.clear();


  std::vector<double> choosex(best_model_num, 0);
  std::vector<double> choosey(best_model_num, 0);
  int k1=0;
  int k2=0;
  for(int j=0; j<num_data; j++) {
    if(best_votes[j]){
      choose[j]=1;
       //std::cout<<j<<" ";
      choosex[k1++]=x[j];
      choosey[k2++]=y[j];
      }
      else{
      choose[j]=0;
      }
  }
  mylr.caltheta(choosex,choosey,best_model_num);
  //std::cout<<"a: "<<mylr.theta1<<" b: "<<mylr.theta0<<std::endl;

  delete []best_votes;
  delete []cur_votes;


  return best_model_num;
}