void EM::read(const FileNode& fn) { Algorithm::read(fn); decomposeCovs(); computeLogWeightDivDet(); }
void clusterTrainSamples() { int nclusters = params.nclusters; int nsamples = trainSamples.rows; // Cluster samples, compute/update means // Convert samples and means to 32F, because kmeans requires this type. Mat trainSamplesFlt, meansFlt; if(trainSamples.type() != CV_32FC1) trainSamples.convertTo(trainSamplesFlt, CV_32FC1); else trainSamplesFlt = trainSamples; if(!means.empty()) { if(means.type() != CV_32FC1) means.convertTo(meansFlt, CV_32FC1); else meansFlt = means; } Mat labels; kmeans(trainSamplesFlt, nclusters, labels, TermCriteria(TermCriteria::COUNT, means.empty() ? 10 : 1, 0.5), 10, KMEANS_PP_CENTERS, meansFlt); // Convert samples and means back to 64F. CV_Assert(meansFlt.type() == CV_32FC1); if(trainSamples.type() != CV_64FC1) { Mat trainSamplesBuffer; trainSamplesFlt.convertTo(trainSamplesBuffer, CV_64FC1); trainSamples = trainSamplesBuffer; } meansFlt.convertTo(means, CV_64FC1); // Compute weights and covs weights = Mat(1, nclusters, CV_64FC1, Scalar(0)); covs.resize(nclusters); for(int clusterIndex = 0; clusterIndex < nclusters; clusterIndex++) { Mat clusterSamples; for(int sampleIndex = 0; sampleIndex < nsamples; sampleIndex++) { if(labels.at<int>(sampleIndex) == clusterIndex) { const Mat sample = trainSamples.row(sampleIndex); clusterSamples.push_back(sample); } } CV_Assert(!clusterSamples.empty()); calcCovarMatrix(clusterSamples, covs[clusterIndex], means.row(clusterIndex), CV_COVAR_NORMAL + CV_COVAR_ROWS + CV_COVAR_USE_AVG + CV_COVAR_SCALE, CV_64FC1); weights.at<double>(clusterIndex) = static_cast<double>(clusterSamples.rows)/static_cast<double>(nsamples); } decomposeCovs(); }
void read(const FileNode& fn) { clear(); read_params(fn["training_params"]); fn["weights"] >> weights; fn["means"] >> means; FileNode cfn = fn["covs"]; FileNodeIterator cfn_it = cfn.begin(); int i, n = (int)cfn.size(); covs.resize(n); for( i = 0; i < n; i++, ++cfn_it ) (*cfn_it) >> covs[i]; decomposeCovs(); computeLogWeightDivDet(); }
bool EM::doTrain(int startStep, OutputArray logLikelihoods, OutputArray labels, OutputArray probs) { int dim = trainSamples.cols; // Precompute the empty initial train data in the cases of EM::START_E_STEP and START_AUTO_STEP if(startStep != EM::START_M_STEP) { if(covs.empty()) { CV_Assert(weights.empty()); clusterTrainSamples(); } } if(!covs.empty() && covsEigenValues.empty() ) { CV_Assert(invCovsEigenValues.empty()); decomposeCovs(); } if(startStep == EM::START_M_STEP) mStep(); double trainLogLikelihood, prevTrainLogLikelihood = 0.; for(int iter = 0; ; iter++) { eStep(); trainLogLikelihood = sum(trainLogLikelihoods)[0]; if(iter >= maxIters - 1) break; double trainLogLikelihoodDelta = trainLogLikelihood - prevTrainLogLikelihood; if( iter != 0 && (trainLogLikelihoodDelta < -DBL_EPSILON || trainLogLikelihoodDelta < epsilon * std::fabs(trainLogLikelihood))) break; mStep(); prevTrainLogLikelihood = trainLogLikelihood; } if( trainLogLikelihood <= -DBL_MAX/10000. ) { clear(); return false; } // postprocess covs covs.resize(nclusters); for(int clusterIndex = 0; clusterIndex < nclusters; clusterIndex++) { if(covMatType == EM::COV_MAT_SPHERICAL) { covs[clusterIndex].create(dim, dim, CV_64FC1); setIdentity(covs[clusterIndex], Scalar(covsEigenValues[clusterIndex].at<double>(0))); } else if(covMatType == EM::COV_MAT_DIAGONAL) { covs[clusterIndex] = Mat::diag(covsEigenValues[clusterIndex]); } } if(labels.needed()) trainLabels.copyTo(labels); if(probs.needed()) trainProbs.copyTo(probs); if(logLikelihoods.needed()) trainLogLikelihoods.copyTo(logLikelihoods); trainSamples.release(); trainProbs.release(); trainLabels.release(); trainLogLikelihoods.release(); return true; }