Sunday 7 April 2013

Randomness - Generating a large pool of features

(Note:  In this entry, the term detection window [DW] refers to the image that we will classify as pedestrian or not pedestrian. It is a section of a larger one)

There are 2 distinct approaches for describing a DW featurewise. Some researchers opt to generate a fine tuned pool of features that are subject to tests until they achieve satisfactory results. This is the case of the HOG classifier, which features constitute of local sums calculated over a dense overlapping grid in the DW. Other approach is to generate random features, knowing that we are guaranteed to get a good characterization of our scene if we our feature pool is large enough. This is the case of the Integral Channel Features [ChnFtrs] algorithm.

In the ChnFtrs approach, a feature has 3 parameters that are generated randomly. Given that we compute different channels of our DW, a feature is calculated on a random channel, over a rectangle which dimensions and position is also random.

In terms of implementation this is how I've done:

  • Create a struct that characterizes one feature
typedef struct
{
  int nFtrs;           //number of features to be calculated
  int channelidx;  // index of the channel where to calculate the feature
  int width;         
  int height;
  int x;                 //up-left x position corner of the random rectangle
  int y;                
//up-left y position corner of the random rectangle
} FtrParams;

  • Create a type of vector for this structs to hold all the parameters.

typedef vector<FtrParams> FtrVecParams;

  • Create a function that initializes this vector with N parameters
For generating random values I use the RNG class of openCV. Using the same seed It is possible to replicate results in the future.

void GetRandParams(int seed, int NrFtrs, FtrVecParams & randparams, Rect region)
{
  cv::RNG rng(seed);
 
  FtrParams Params;
  Params.nFtrs=NrFtrs;
 
  for (int n=0; n<NrFtrs; n++)
  {
    Params.channelidx=rng.uniform(0,CHANNELNR);
   
    //rng.uniform(x,y) returns a value between x and y
   
    Params.width=rng.uniform(5,region.width+1); 
    Params.height=rng.uniform(5,region.height+1);
   
    Params.x=rng.uniform(0,region.width-Params.width+1);
    Params.y=rng.uniform(0,region.height-Params.height+1);
   
    randparams.push_back(Params); //fills randparams (wich is declared
                                                          //elsewhere).   
  }
 
}

The Rect Region in the input arguments has the information of our DW size.

  • Calculating features over a DW
For this we need to functions:

void GetChnFtrsOverWindow(Mat IntegralChannels , vector<float> & features, vector<DVector> & WindowFtrs ,FtrVecParams Params, CvRect region)
{
  vector<float> aux;
 
  for (int n=0; n< Params[0].nFtrs ; n++)
  {
    
      GetIntegralSum(IntegralChannels,features ,Params[n],region);

  }
  

//the code below organizes the data in a vector in which each index has the //features of one DW.

  for(int n=0; n<NRFEATURE; n++)
  {
    aux.push_back(features[features.size()-NRFEATURE+n]);
  }
 
  WindowFtrs.push_back(aux);
 
}


And

void GetIntegralSum(Mat IntegralChannels, vector<float> & features,FtrParams Params, CvRect region)
{
 
  vec10d tl, tr, bl, br;
  int sR=Params.y+region.y, sC=Params.x+region.x, eR=sR+Params.height, eC=sC+Params.width, sum;
 
  tl= IntegralChannels.at<vec10d>(sR,sC);
  tr= IntegralChannels.at<vec10d>(sR,eC);
  bl= IntegralChannels.at<vec10d>(eR,sC);
  br= IntegralChannels.at<vec10d>(eR,eC);
 
 
  sum=br[Params.channelidx]-bl[Params.channelidx]-tr[Params.channelidx]+tl[Params.channelidx];
 
  features.push_back(sum);
 
}

I've already started playing with the openCV CvBoost class, for classification, but I've yet to get any meaningful results out of it, so I'll leave it to the next entry

Regards!


No comments:

Post a Comment