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); }
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; }