vector<int> Recoloring::MatchGaussians(CvEM& source_model, CvEM& target_model) { int num_g = source_model.get_nclusters(); Mat sMu(source_model.get_means()); Mat tMu(target_model.get_means()); const CvMat** target_covs = target_model.get_covs(); const CvMat** source_covs = source_model.get_covs(); double best_dist = std::numeric_limits<double>::max(); vector<int> best_res(num_g); vector<int> prmt(num_g); for(int itr = 0; itr < 10; itr++) { for(int i=0;i<num_g;i++) prmt[i] = i; //make a permutation randShuffle(Mat(prmt)); //Greedy selection vector<int> res(num_g); vector<bool> taken(num_g); for(int sg = 0; sg < num_g; sg++) { double min_dist = std::numeric_limits<double>::max(); int minv = -1; for(int tg = 0; tg < num_g; tg++) { if(taken[tg]) continue; //TODO: can save on re-calculation of pairs - calculate affinity matrix ahead //double d = norm(sMu(Range(prmt[sg],prmt[sg]+1),Range(0,3)), tMu(Range(tg,tg+1),Range(0,3))); //symmetric kullback-leibler Mat diff = Mat(sMu(Range(prmt[sg],prmt[sg]+1),Range(0,3)) - tMu(Range(tg,tg+1),Range(0,3))); Mat d = diff * Mat(Mat(source_covs[prmt[sg]]).inv() + Mat(target_covs[tg]).inv()) * diff.t(); Scalar tr = trace(Mat( Mat(Mat(source_covs[prmt[sg]])*Mat(target_covs[tg])) + Mat(Mat(target_covs[tg])*Mat(source_covs[prmt[sg]]).inv()) + Mat(Mat::eye(3,3,CV_64FC1)*2) )); double kl_dist = ((double*)d.data)[0] + tr[0]; if(kl_dist<min_dist) { min_dist = kl_dist; minv = tg; } } res[prmt[sg]] = minv; taken[minv] = true; } double dist = 0; for(int i=0;i<num_g;i++) { dist += norm(sMu(Range(prmt[i],prmt[i]+1),Range(0,3)), tMu(Range(res[prmt[i]],res[prmt[i]]+1),Range(0,3))); } if(dist < best_dist) { best_dist = dist; best_res = res; } } return best_res; }
float* pkmGaussianMixtureModel::getClusterMean(int clusterNum) { cout << "Variables: " << m_nVariables << endl; float *returnedMeans = new float[m_nVariables]; if(bModeled) { CvEM *myModel = emModel + bestModel; int numClusters = myModel->get_nclusters(); cout << "numClusters: " << numClusters << endl; if (clusterNum < numClusters) { const CvMat *modelMus = myModel->get_means(); if (modelMus != NULL) { cout << "mus rows: " << modelMus->rows << " cols: " << modelMus->cols << endl; for (int i = 0; i < m_nVariables; i++) { returnedMeans[i] = cvmGet(modelMus, clusterNum, i); } } } else { for (int i = 0; i < m_nVariables; i++) { returnedMeans[i] = 0; } } } else { for (int i = 0; i < m_nVariables; i++) { returnedMeans[i] = 0; } } return returnedMeans; }
int pkmGaussianMixtureModel::writeToFile(ofstream &fileStream, bool writeClusterNums, bool writeWeights, bool writeMeans, bool writeCovs, bool verbose) { if(!fileStream.is_open()) return -1; // use the best-model CvEM myModel = emModel[bestModel]; const CvMat **modelCovs = myModel.get_covs(); const CvMat *modelMus = myModel.get_means(); const CvMat *modelWeights = myModel.get_weights(); int numClusters = myModel.get_nclusters(); // output the total number of clusters if(writeClusterNums) { if(verbose) fileStream << "Number of Clusters: " << numClusters << "\n"; else fileStream << numClusters << "\n"; } if(writeWeights) { // output the weights of each cluster if(verbose) fileStream << "Weight of Clusters\n"; for (int k = 0; k < numClusters; k++) { const double *weightPtr = (const double *)(modelWeights->data.ptr + k*modelWeights->step); double weight = weightPtr[0]; if(verbose) fileStream << k << ": " << weight << "\n"; else fileStream << weight << " "; } fileStream << "\n"; } if(writeMeans) { // output the means of each cluster if(verbose) fileStream << "Means of Clusters\n"; for (int k = 0; k < numClusters; k++) { if(verbose) fileStream << "Cluster " << k << ":\n"; for (int i = 0; i < m_nVariables; i++) { if(verbose) fileStream << i << ": " << cvmGet(modelMus, k, i) << " "; else fileStream << cvmGet(modelMus, k, i) << " "; } fileStream << "\n"; } } if(writeCovs) { // output the covariances of each cluster if(verbose) fileStream << "Covariances of Clusters\n"; for (int k = 0; k < numClusters; k++) { const CvMat * covar = modelCovs[k]; if(verbose) fileStream << "Cluster " << k << ":\n"; for (int i = 0; i < m_nVariables; i++) { for (int j = 0; j < m_nVariables; j++) { if(verbose) fileStream << i << "," << j << ": " << cvmGet(covar, i, j) << " "; else fileStream << cvmGet(covar, i, j) << " "; } } fileStream << "\n"; } } return 0; }
/*void pkmGaussianMixtureModel::getLikelihood(int x, int y) { } */ void pkmGaussianMixtureModel::getLikelihoodMap(int rows, int cols, unsigned char *map, ofstream &filePtr, int widthstep) { if(widthstep == 0) widthstep = cols; if(!bModeled) return; CvEM myModel = emModel[bestModel]; const CvMat **modelCovs = myModel.get_covs(); const CvMat *modelMus = myModel.get_means(); const CvMat *modelWeights = myModel.get_weights(); int numClusters = myModel.get_nclusters(); CvMat *pts = cvCreateMat(m_nVariables, 1, CV_64FC1); CvMat *mean = cvCreateMat(m_nVariables, 1, CV_64FC1); double p = 0; double weight; double max = 0; double prob; filePtr << "clusters: " << numClusters << "\n"; filePtr << "likelihood: " << m_Likelihood << "\n"; filePtr << "BIC: " << m_BIC << "\n"; //printf("clusters: %d\n", numClusters); float best_weight = 0; bestCluster = 0; for (int k = 0; k < numClusters; k++) { const CvMat * covar = modelCovs[k]; //printf("covar: (%f, %f, %f, %f)\n", covar->data.ptr[0], \ covar->data.ptr[1], \ covar->data.ptr[2], \ covar->data.ptr[3]); //const double *meanVals = (const double *)(modelMus->data.ptr + k*modelWeights->step); cvmSet(mean, 0, 0, cvmGet(modelMus, k, 0)); cvmSet(mean, 1, 0, cvmGet(modelMus, k, 1)); //const double *weightPtr = (const double *)(modelWeights->data.ptr + k*modelWeights->step); //weight = weightPtr[k]; weight = cvmGet(modelWeights, 0, k); if (best_weight < weight) { best_weight = weight; bestCluster = k; } filePtr << "mean: " << cvmGet(modelMus, k, 0)*(double)m_nScale << " " << cvmGet(modelMus, k, 1)*(double)m_nScale << "\n"; filePtr << "covar: " << cvmGet(covar, 0, 0) << "\n"; filePtr << "weight: " << weight << "\n"; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { cvmSet(pts, 0, 0, (double)j); cvmSet(pts, 1, 0, (double)i); prob = multinormalDistribution(pts, mean, covar); map[j+i*widthstep] += (int)((weight * prob)*(double)(rows*cols)); } } } cvReleaseMat(&mean); cvReleaseMat(&pts); }