⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fams.cpp

📁 mean-shift算法的实现算例
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/////////////////////////////////////////////////////////////////////////////
// Name:        fams.cpp
// Purpose:     fast adaptive meanshift implementation
// Author:      Ilan Shimshoni
// Modified by: Bogdan Georgescu
// Created:     08/14/2003
// Version:     v0.1
/////////////////////////////////////////////////////////////////////////////

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#include <memory.h>
#include <time.h>
#include "fams.h"


FAMS::FAMS(int no_lsh)
{
   hasPoints_ = 0;
   nsel_ = 0;
   npm_ = 0;
   hashCoeffs_ = NULL;
   noLSH_=no_lsh;

   time_t tt1;
   time(&tt1);
   srand((unsigned)tt1);
//   srand(100);

   nnres1_ = 0;
   nnres2_ = 0;
}

FAMS::~FAMS()
{
   CleanData();
   
}

void FAMS::CleanData()
{
   CleanPoints();
   CleanSelected();
   CleanPrunedModes();
   CleanHash();
}

void FAMS::CleanPoints()
{
   if (hasPoints_)
   {
      delete [] points_;
      delete [] data_;
      delete [] rr_;
      hasPoints_ = 0;
   }
}

void FAMS::CleanSelected()
{
   if (nsel_ > 0)
   {
      delete [] psel_;
      delete [] modes_;
      delete [] hmodes_;
      nsel_ = 0;
   }
}

void FAMS::CleanPrunedModes()
{
   if (npm_ > 0)
   {
      delete [] prunedmodes_;
      delete [] nprunedmodes_;
      npm_ = 0;
   }
}

void FAMS::CleanHash()
{
   if (hashCoeffs_ != NULL)
   {
      delete [] hashCoeffs_;
      hashCoeffs_ = NULL;
   }
}

int FAMS::LoadPoints(char* filename)
{
   bgLog("Load data points from %s...",filename);
   CleanPoints();
   FILE* fd;
   fd = fopen(filename, "r");

   if (!fd)
   {
      bgLog("Error opening %s\n", filename);
      return 1;
   }
   fscanf(fd, "%d %d", &n_, &d_);
   if ((n_<1) || (d_<1))
   {
      bgLog("Error reading %s\n", filename);
      fclose(fd);
      return 1;
   }

   // allocate data
   float* pttemp;
   pttemp = new float[n_*d_];
   int i;
   for (i=0; (i<(n_*d_)) && (fscanf(fd, "%g", &pttemp[i]) == 1); i++);
   fclose(fd);

   if (i!= (n_*d_))
   {
      bgLog("Error reading %s\n", filename);
      delete [] pttemp;
      return 1;
   }

   // allocate and convert to integer
   for (i=0, minVal_=pttemp[0], maxVal_=pttemp[0]; i<(n_*d_); i++)
   {
      if (minVal_>pttemp[i])
         minVal_ = pttemp[i];
      else if (maxVal_<pttemp[i])
         maxVal_ = pttemp[i];
   }
   data_ = new unsigned short[n_*d_];
   rr_ = new double[d_];
   hasPoints_ = 1;
   float deltaVal = maxVal_-minVal_;
   if (deltaVal == 0) deltaVal = 1;
   for (i=0; i<(n_*d_); i++)
      data_[i] = (unsigned short) (65535.0*(pttemp[i]-minVal_)/deltaVal);
   delete [] pttemp;
   dataSize_ = d_*sizeof(unsigned short);

   points_ = new fams_point[n_];
   unsigned short* dtempp;
   for (i=0, dtempp=data_; i<n_; i++, dtempp+=d_)
   {
      points_[i].data_ = dtempp;
      points_[i].usedFlag_ = 0;
   }
   bgLog("done\n");
   return 0;
}


// Choose a subset of points on which to perform the mean shift operation 
void FAMS::SelectMsPoints(double percent,int jump)
{
   if (hasPoints_ == 0)
      return;
   int i;
   int tsel;
   if(percent){
      tsel = (int)(n_*percent/100.0);
      if (tsel != nsel_)
      {
         CleanSelected();
         nsel_ = tsel;
         psel_ = new int[nsel_];
         modes_ = new unsigned short[nsel_*d_];
         hmodes_ = new unsigned int[nsel_];
      }
      for(i=0; i<nsel_;  i++)
         psel_[i] = MyMin(n_-1,(int)(drand48()*n_));
   }
   else
   {
      tsel = (int)ceil(n_/(jump+0.0));
      if (tsel != nsel_)
      {
         CleanSelected();
         nsel_ = tsel;
         psel_ = new int[nsel_];
         modes_ = new unsigned short[nsel_*d_];
         hmodes_ = new unsigned int[nsel_];
      }
      for(i=0; i<nsel_; i++)
         psel_[i]=i*jump;
   }
}

void FAMS::MakeCuts(fams_partition* cuts)
{
   int i;
   for(i=0; i<L_; i++)
      MakeCutL(cuts[i]);
}

// data-driven uniform partition

void FAMS::MakeCutL(fams_partition& cut)
{
   int n1 = (int)floor(K_/(1.0*d_));
   int i,j;
   int ncu=0;
   int w;
   for(i=0; i<d_; i++)
   {
      for(j=0; j<n1; j++)
      {
         cut[ncu].which_ = i;
         w = MyMin((int)(drand48()*n_),n_-1);
         cut[ncu].where_ = points_[w].data_[i];
         ncu++;
      }
   }
   /*
   int *which = new int[d_];
   for (i=0; i<d_; i++)
      which[i]=i;
   int wh, ndleft, itmp;
   ndleft = d_;
   for (i=0; i<(K_-ncu); i++)
   {
      wh = MyMin((int)(drand48()*ndleft),ndleft-1);
      itmp = which[wh+i];
      which[wh+i] = which[i];
      which[i] = itmp;
      ndleft--;
   }

   for(i=0 ; ncu < K_; ncu++, i++)
   {
      w = MyMin((int)(drand48()*n_),n_-1);
      cut[ncu].which_ = which[i];
      cut[ncu].where_ = points_[w].data_[which[i]];
   }
   delete [] which;
   */
   int *which = new int[d_];
   memset(which,0,sizeof(int)*d_);
   for (; ncu<K_; )
   {
      int wh = MyMin((int)(drand48()*d_),d_-1);
      if(which[wh]!=0)
         continue;
      which[wh]=1;
      int w = MyMin((int)(drand48()*n_), n_-1);
      cut[ncu].which_ = wh;
      cut[ncu].where_ = points_[w].data_[wh];
      ncu++;
   }
   delete [] which;
}

void FAMS::InitHash(int nk)
{
   CleanHash();
   hashCoeffs_ = new int[nk];
   for(int i=0; i<nk; i++)
      hashCoeffs_[i] = rand();
}

/* compute the hash key and and the double hash key if needed 
It is possible to give M the the size of the hash table and 
hjump for the double hash key 
*/

int FAMS::HashFunction(int *cutVals, int whichPartition, int kk,int M,int *hjump)
{
   int i;
   int res = whichPartition;
   for(i=0; i<kk; i++)
   {
      res += cutVals[i]*hashCoeffs_[i];
   }
   if(M)
   {
      res = abs(res);
      if(hjump)
         *hjump = (res%(M-1))+1;
      res = res%M;
   }
   return res;
}


// Add a point to the LSH hash table using double hashing 
void FAMS::AddDataToHash(block HT[],int hs[],fams_point& pt,int where,int Bs,int M,int which,int which2,
                      int hjump)
{
   int nw=0;
   for(;;where = (where+hjump)%M)
   {
      nw++;
      if(nw > M)
      {
         bgLog("LSH hash table overflow exiting\n");
         exit(-1);
      }
      if(hs[where] == Bs)
         continue;
      HT[where][hs[where]].pt_ = &pt;
      HT[where][hs[where]].whichCut_ = which;
      HT[where][hs[where]].which2_ = which2;
      hs[where]++;
      break;
   }
}

// compute the pilot h_i's for the data points
void FAMS::ComputePilot(block *HT,int *hs, fams_partition *cuts, char* pilot_fn)
{
   const int win_j = 10,max_win=7000;
   int i,j;
   unsigned int nn;
   unsigned int wjd = (unsigned int)(win_j*d_);
   int num_l[1000];
   fams_res_cont res(n_);
   if(LoadBandwidths(pilot_fn)==0)
   {
      bgLog("compute bandwidths...");
      for(j=0; j<n_; j++)
      { 
         int numn=0;
         int numns[max_win/win_j];
         memset(numns,0,sizeof(numns));
         int nel;
         if(noLSH_)
         {
            nel = n_;
            for(i=0; i<nel; i++)
            {
               fams_pointp pt = &points_[i];
               nn = DistL1(points_[j],*pt) / wjd;
               if(nn <max_win/win_j)
                  numns[nn]++;	
            }
         }
         else
         {
            GetNearestNeighbours(points_[j],HT,hs,cuts,res,0,num_l);
            nel = res.nel_;      
            for(i=0; i<nel; i++)
            {
               fams_pointp pt = res.vec_[i];
               nn = DistL1(points_[j],*pt) / wjd;
               if(nn <max_win/win_j)
                  numns[nn]++;	
            }
         }
         for(nn=0; nn<max_win/win_j; nn++)
         {
            numn+=numns[nn];
            if(numn>k_)
            {
               break;
            }
         }	
         points_[j].window_=(nn+1)*wjd;
      }
      SaveBandwidths(pilot_fn);
   }
   else
      bgLog("load bandwidths...");
   for(j=0; j<n_; j++){
      points_[j].weightdp2_ = (float) pow(FAMS_FLOAT_SHIFT/points_[j].window_, (d_+2)*FAMS_ALPHA);
//      points_[j].weightdp2_ = (float) (1.0/pow(points_[j].window_, (d_+2)*FAMS_ALPHA));
   }
}

// compute real bandwiths for selected points
void FAMS::ComputeRealBandwidths(unsigned int h)
{
   const int win_j = 10,max_win=7000;
   int i,j;
   unsigned int nn;
   unsigned int wjd;
   wjd = (unsigned int) (win_j*d_);
   int who;
   if (h==0)
   {
      for(j=0; j<nsel_; j++)
      {
         who = psel_[j];
         int numn=0;
         int numns[max_win/win_j];
         memset(numns,0,sizeof(numns));
         for(i=0; i<n_; i++)
         {
            fams_pointp pt = &points_[i];
            nn = DistL1(points_[who],*pt) / wjd;
            if(nn <max_win/win_j)
               numns[nn]++;	
         }
         for(nn=0; nn<max_win/win_j; nn++)
         {
            numn+=numns[nn];
            if(numn>k_)
            {
               break;
            }
         }	
         points_[who].window_=(nn+1)*win_j;
      }
   } else
   {
      for(j=0; j<nsel_; j++)
      {
         who = psel_[j];
         points_[who].window_=h;
      }
   }
}

// compute the pilot h_i's for the data points
void FAMS::ComputeScores(block *HT,int *hs, fams_partition *cuts, float* scores)
{
   const int win_j = 10,max_win=7000;
   int i,j,who;
   unsigned int nn;
   unsigned int wjd = (unsigned int)(win_j*d_);
   int num_l[1000];
   memset(scores, 0, L_*sizeof(float));
   fams_res_cont res(n_);
   for(j=0; j<nsel_; j++)
   { 
      who = psel_[j];
      int numn;
      int nl=0;
      int numns[max_win/win_j];
      memset(numns,0,sizeof(numns));
      int nel;
      if(noLSH_)
      {
         nel = n_;
         num_l[L_]=n_+1;
         for(i=0; i<nel; i++)
         {
            fams_pointp pt = &points_[i];
            nn = DistL1(points_[who],*pt) / wjd;
            if(nn <max_win/win_j)
               numns[nn]++;	
            if(i == (num_l[nl]-1))
            {
               numn=0;
               for(nn=0; nn<max_win/win_j; nn++)
               {
                  if(numn>k_)
                     break;
               }
               for(; (num_l[nl]-1) == i; nl++)
                  scores[nl] += (float) (((nn+1.0)*win_j)/points_[who].window_);
            }
         }
      }
      else
      {
         GetNearestNeighbours(points_[who],HT,hs,cuts,res,0,num_l);
         nel = res.nel_;
         num_l[L_] = n_+1;
         for(i=0; i<nel; i++)
         {
            fams_pointp pt = res.vec_[i];
            nn = DistL1(points_[who],*pt) / wjd;
            if(nn <max_win/win_j)
               numns[nn]++;
            if(i == (num_l[nl]-1))
            {
               numn=0;
               for(nn=0; nn<max_win/win_j; nn++)
               {
                  numn+=numns[nn];
                  if(numn>k_)
                     break;
               }
               for(; (num_l[nl]-1) == i; nl++)
                  scores[nl] += (float) (((nn+1.0)*win_j)/points_[who].window_);
            }
         }
      }
      numn=0;
      for(nn=0; nn<max_win/win_j; nn++)
      {
         numn+=numns[nn];
         if(numn>k_)
            break;
      }	
   }
   for(j=0; j<L_; j++)
      scores[j]/=nsel_;

}

/*
Insert an mean-shift result into a second hash table so when another mean shift computationis 
performed about the same C_intersection region, the result can be retreived without further 
computation
*/

void FAMS::InsertIntoHash(block2* HT2,int *hs2,int where,int which,
                    unsigned short **solution,int M,int hjump)
{
   int nw=0;
   for(;;where = (where+hjump)%M)
   {
      nw++;
      if(nw==M)
      {
         bgLog("Second Hash Table Full\n");
         exit(-1);
      }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -