bool utfConvert( const std::basic_string<From>& from, std::basic_string<To>& to, ConversionResult(*cvtfunc)(const typename FromTrait::ArgType**, const typename FromTrait::ArgType*, typename ToTrait::ArgType**, typename ToTrait::ArgType*, ConversionFlags) ) { static_assert(sizeof(From) == sizeof(typename FromTrait::ArgType), "Error size mismatched"); static_assert(sizeof(To) == sizeof(typename ToTrait::ArgType), "Error size mismatched"); if (from.empty()) { to.clear(); return true; } // See: http://unicode.org/faq/utf_bom.html#gen6 static const int most_bytes_per_character = 4; const size_t maxNumberOfChars = from.length(); // all UTFs at most one element represents one character. const size_t numberOfOut = maxNumberOfChars * most_bytes_per_character / sizeof(To); std::basic_string<To> working(numberOfOut, 0); auto inbeg = reinterpret_cast<const typename FromTrait::ArgType*>(&from[0]); auto inend = inbeg + from.length(); auto outbeg = reinterpret_cast<typename ToTrait::ArgType*>(&working[0]); auto outend = outbeg + working.length(); auto r = cvtfunc(&inbeg, inend, &outbeg, outend, strictConversion); if (r != conversionOK) return false; working.resize(reinterpret_cast<To*>(outbeg) - &working[0]); to = std::move(working); return true; };
void operator()(const BlockedRange& range) const { int y0 = range.begin(), y1 = range.end(); int ncols = src->cols, nchannels = src->channels(); AutoBuffer<float> buf(src->cols*nchannels); float alpha1 = 1.f - alphaT; float dData[CV_CN_MAX]; for( int y = y0; y < y1; y++ ) { const float* data = buf; if( cvtfunc ) cvtfunc( src->ptr(y), src->step, 0, 0, (uchar*)data, 0, Size(ncols*nchannels, 1), 0); else data = src->ptr<float>(y); float* mean = mean0 + ncols*nmixtures*nchannels*y; GMM* gmm = gmm0 + ncols*nmixtures*y; uchar* modesUsed = modesUsed0 + ncols*y; uchar* mask = dst->ptr(y); for( int x = 0; x < ncols; x++, data += nchannels, gmm += nmixtures, mean += nmixtures*nchannels ) { //calculate distances to the modes (+ sort) //here we need to go in descending order!!! bool background = false;//return value -> true - the pixel classified as background //internal: bool fitsPDF = false;//if it remains zero a new GMM mode will be added int nmodes = modesUsed[x], nNewModes = nmodes;//current number of modes in GMM float totalWeight = 0.f; float* mean_m = mean; ////// //go through all modes for( int mode = 0; mode < nmodes; mode++, mean_m += nchannels ) { float weight = alpha1*gmm[mode].weight + prune;//need only weight if fit is found //// //fit not found yet if( !fitsPDF ) { //check if it belongs to some of the remaining modes float var = gmm[mode].variance; //calculate difference and distance float dist2; if( nchannels == 3 ) { dData[0] = mean_m[0] - data[0]; dData[1] = mean_m[1] - data[1]; dData[2] = mean_m[2] - data[2]; dist2 = dData[0]*dData[0] + dData[1]*dData[1] + dData[2]*dData[2]; } else { dist2 = 0.f; for( int c = 0; c < nchannels; c++ ) { dData[c] = mean_m[c] - data[c]; dist2 += dData[c]*dData[c]; } } //background? - Tb - usually larger than Tg if( totalWeight < TB && dist2 < Tb*var ) background = true; //check fit if( dist2 < Tg*var ) { ///// //belongs to the mode fitsPDF = true; //update distribution //update weight weight += alphaT; float k = alphaT/weight; //update mean for( int c = 0; c < nchannels; c++ ) mean_m[c] -= k*dData[c]; //update variance float varnew = var + k*(dist2-var); //limit the variance varnew = MAX(varnew, varMin); varnew = MIN(varnew, varMax); gmm[mode].variance = varnew; //sort //all other weights are at the same place and //only the matched (iModes) is higher -> just find the new place for it for( int i = mode; i > 0; i-- ) { //check one up if( weight < gmm[i-1].weight ) break; //swap one up std::swap(gmm[i], gmm[i-1]); for( int c = 0; c < nchannels; c++ ) std::swap(mean[i*nchannels + c], mean[(i-1)*nchannels + c]); } //belongs to the mode - bFitsPDF becomes 1 ///// } }//!bFitsPDF) //check prune if( weight < -prune ) { weight = 0.0; nmodes--; } gmm[mode].weight = weight;//update weight by the calculated value totalWeight += weight; } //go through all modes ////// //renormalize weights totalWeight = 1.f/totalWeight; for( int mode = 0; mode < nmodes; mode++ ) { gmm[mode].weight *= totalWeight; } nmodes = nNewModes; //make new mode if needed and exit if( !fitsPDF ) { // replace the weakest or add a new one int mode = nmodes == nmixtures ? nmixtures-1 : nmodes++; if (nmodes==1) gmm[mode].weight = 1.f; else { gmm[mode].weight = alphaT; // renormalize all other weights for( int i = 0; i < nmodes-1; i++ ) gmm[i].weight *= alpha1; } // init for( int c = 0; c < nchannels; c++ ) mean[mode*nchannels + c] = data[c]; gmm[mode].variance = varInit; //sort //find the new place for it for( int i = nmodes - 1; i > 0; i-- ) { // check one up if( alphaT < gmm[i-1].weight ) break; // swap one up std::swap(gmm[i], gmm[i-1]); for( int c = 0; c < nchannels; c++ ) std::swap(mean[i*nchannels + c], mean[(i-1)*nchannels + c]); } } //set the number of modes modesUsed[x] = uchar(nmodes); mask[x] = background ? 0 : detectShadows && detectShadowGMM(data, nchannels, nmodes, gmm, mean, Tb, TB, tau) ? shadowVal : 255; } } }