Beispiel #1
0
	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);
}