VectorDouble stddev(VectorDouble v) {
    double sum = std::accumulate(v.begin(), v.end(), 0.0);
    double mean = sum / v.size();

    double sq_sum = std::inner_product(v.begin(), v.end(), v.begin(), 0.0);
    double stdev = std::sqrt(sq_sum / v.size() - mean * mean);
    
    return VectorDouble(1, stdev);
}
Example #2
0
double  SegmentorOTSU::sig_func (VectorDouble          k,
                                 kkint32               nbins,
                                 const VectorDouble&   P,
                                 kkint32               numClasses
                                )
{
  kkint32 x = 0, y = 0;

  // muT = sum((1:nbins).*P);
  double  muT = 0.0;
  for  (x = 0, y = 1;  x < nbins;  ++x, ++y)
    muT += y * P[x];

  //sigma2T = sum(((1:nbins)-muT).^2.*P);
  double  sigma2T = 0.0;
  for  (x = 0, y = 1;  x < nbins;  ++x, ++y)
    sigma2T +=  (pow ((y - muT), 2.0) * P[x]);

  //k = round(k*(nbins-1)+1);
  for  (x = 0;  x < (kkint32)k.size ();  ++x)
    k[x] = floor (k[x] * (nbins - 1) + 1.0 + 0.5);

  //k = sort(k);
  sort (k.begin (), k.end ());

  //if any(k<1 | k>nbins), y = 1; return, end
  if  ((k[0] < 1.0)  ||  (k[k.size () - 1] > nbins))
    return 1.0;
        
  //k = [0 k nbins];   %  Puts '0' at beginning and 'nbins' at the end.
  k.insert (k.begin (), 0.0);
  k.push_back (nbins);

  // sigma2B = 0;
  double  sigma2B = 0.0;

  //for j = 1:numClasses
  for  (kkint32 j = 0;  j < numClasses;  ++j)
  {
    //wj = sum(P(k(j)+1:k(j+1)));
    double  wj = SumSubSet (P, (kkint32)(k[j] + 1), (kkint32)k[j + 1]);

    //if wj==0, y = 1; return, end
    if  (wj == 0.0)
      return 1.0;

    //muj = sum((k(j)+1:k(j+1)).*P(k(j)+1:k(j+1)))/wj;
    kkint32  idxStart = (kkint32)(k[j] + 1);
    kkint32  idxEnd   = (kkint32)(k[j + 1]);
    double  muj = 0.0;
    for  (kkint32 i = idxStart;  i <= idxEnd;  ++i)
      muj += (i * P[i] / wj);

    //sigma2B = sigma2B + wj*(muj-muT)^2;
    sigma2B = sigma2B + wj * pow ((muj - muT), 2.0);
  }

  //y = 1-sigma2B/sigma2T; % within the range [0 1]
  return  1.0 - sigma2B / sigma2T;
}  /* sig_func */
TrainingSampleCheckerResult checkTrainingSample(const MatrixDouble &in) {
    VectorDouble stddev = in.getStdDev();
    if (*max_element(stddev.begin(), stddev.end()) < 0.1)
        return TrainingSampleCheckerResult(TrainingSampleCheckerResult::WARNING,
            "Warning: Gesture contains very little movement.");
    return TrainingSampleCheckerResult::SUCCESS;
}