1 #include "TrainNodeGMM.h" 47 inline std::vector<double> getDistance(
const Mat &x,
const GaussianMixture &gaussianMixture,
size_t samplesTreshold,
double dist_Etreshold,
double dist_Mtreshold)
49 std::vector<double> res(gaussianMixture.size());
50 for (
size_t i = 0; i < res.size(); i++)
52 res[i] = gaussianMixture[i].getEuclidianDistance(x);
54 res[i] = gaussianMixture[i].getNumPoints() >= samplesTreshold ? gaussianMixture[i].getMahalanobisDistance(x)
55 : gaussianMixture[i].getEuclidianDistance(x) * dist_Mtreshold / dist_Etreshold;
62 inline std::vector<double> getDivergence(
const CKDGauss &x,
const GaussianMixture &gaussianMixture,
size_t samplesTreshold)
64 std::vector<double> res(gaussianMixture.size());
65 for (
size_t i = 0; i < res.size(); i++)
66 res[i] = gaussianMixture[i].getNumPoints() >= samplesTreshold ? x.getKullbackLeiberDivergence(gaussianMixture[i]) : DBL_MAX;
73 DGM_ASSERT_MSG(gt <
m_nStates,
"The groundtruth value %u is out of range [0; %u)", gt,
m_nStates);
76 featureVector.convertTo(point, CV_64FC1);
80 if (gaussianMixture.empty())
81 gaussianMixture.emplace_back(point);
86 auto it = std::min_element(dist.begin(), dist.end());
93 gaussianMixture.emplace_back(point);
95 size_t updIdx = std::distance(dist.begin(), it);
96 CKDGauss &updGauss = gaussianMixture[updIdx];
102 std::vector<double> div = getDivergence(updGauss, gaussianMixture,
m_params.
minSamples);
103 div[updIdx] = DBL_MAX;
106 auto it = std::min_element(div.begin(), div.end());
110 size_t idx = std::distance(div.begin(), it);
111 gaussianMixture[idx] += updGauss;
112 gaussianMixture.erase(gaussianMixture.begin() + updIdx);
121 void printMat(
const std::string &name,
const Mat &m) {
122 if (!name.empty()) printf(
"%s:\n", name.c_str());
123 for (
int y = 0; y < m.rows; y++) {
124 for (
int x = 0; x < m.cols; x++)
125 printf(
"%.1f\t", m.at<T>(y, x));
130 void printStatus(std::vector<GaussianMixture> &vGaussianMixtures,
long double minCoefficient) {
131 #ifdef DEBUG_PRINT_INFO 132 printf(
"\nCTrainNodeGMM::Status\n");
133 printf(
"---------------------------\n");
134 printf(
"( minCoefficient = %Le )\n", minCoefficient);
136 for (
size_t s = 0; s < vGaussianMixtures.size(); s++) {
137 printf(
"Class %zu (%zu gausses):\n", s, vGaussianMixtures[s].size());
140 for (
const CKDGauss &gauss : vGaussianMixtures[s]) {
141 printf(
"\tG[%u]: %zupts; ", g++, gauss.getNumPoints());
142 printf(
"alpha: %Le;\n", gauss.getAlpha());
158 for (
auto it = gaussianMixture.begin(); it != gaussianMixture.end(); it++) {
159 size_t nPoints = it->getNumPoints();
162 size_t g = std::distance(gaussianMixture.begin(), it);
167 auto itm = std::min_element(div.begin(), div.end());
168 if (itm != div.end()) {
169 size_t gaussIdx = std::distance(div.begin(), itm);
170 gaussianMixture[gaussIdx] += (*it);
173 gaussianMixture.erase(it);
181 for (
auto itGauss = gaussianMixture.begin(); itGauss != gaussianMixture.end(); itGauss++) {
182 long double alpha = itGauss->getAlpha();
184 gaussianMixture.erase(itGauss);
207 word nGausses =
static_cast<word
>(gaussianMixture.size());
208 fwrite(&nGausses,
sizeof(word), 1, pFile);
209 for (
const CKDGauss &gauss : gaussianMixture) {
210 size_t nPoints = gauss.getNumPoints();
211 Mat mu = gauss.getMu();
212 Mat sigma = gauss.getSigma();
214 fwrite(&nPoints,
sizeof(
long), 1, pFile);
216 fwrite(&mu.at<
double>(y, 0),
sizeof(double), 1, pFile);
219 fwrite(&sigma.at<
double>(y, x),
sizeof(double), 1, pFile);
225 fwrite(&
m_minAlpha,
sizeof(
long double), 1, pFile);
241 fread(&nGausses,
sizeof(word), 1, pFile);
243 for (
CKDGauss &gauss : gaussianMixture) {
248 fread(&nPoints,
sizeof(
long), 1, pFile);
250 fread(&mu.at<
double>(y, 0),
sizeof(double), 1, pFile);
253 fread(&sigma.at<
double>(y, x),
sizeof(double), 1, pFile);
256 gauss.setSigma(sigma);
257 gauss.setNumPoints(nPoints);
264 fread(&
m_minAlpha,
sizeof(
long double), 1, pFile);
270 Mat aux1, aux2, aux3;
272 featureVector.convertTo(fv, CV_64FC1);
277 if (gaussianMixture.empty()) mask.at<byte>(s, 0) = 0;
279 size_t nAllPoints = 0;
280 for (
const CKDGauss &gauss : gaussianMixture)
281 nAllPoints += gauss.getNumPoints();
283 for (
const CKDGauss &gauss : gaussianMixture) {
284 double k =
static_cast<double>(gauss.getNumPoints()) / nAllPoints;
285 double value = gauss.getValue(fv, aux1, aux2, aux3);
286 long double aK = gauss.getAlpha() /
m_minAlpha;
287 potential.at<
float>(s, 0) += static_cast<float>(k * aK * value);
void saveFile(FILE *pFile) const
Saves the random model into the file.
double dist_Etreshold
Minimum Euclidean distance between Gauss functions.
double div_KLtreshold
Minimum Kullback-Leiber divergence between Gauss functions. If this parameter is negative, the merging of Gaussians in addFeatureVec() function will be disabled.
word getNumFeatures(void) const
Returns number of features.
void reset(void)
Resets class variables.
void train(bool doClean=false)
Random model training.
Gaussian Mixture Model parameters.
CTrainNodeGMM(byte nStates, word nFeatures, TrainNodeGMMParams params=TRAIN_NODE_GMM_PARAMS_DEFAULT)
Constructor.
static const long double MAX_COEFFICIENT
Base abstract class for random model training.
word maxGausses
The maximal number of Gauss functions for approximation.
static const size_t MIN_SAMPLES
void calculateNodePotentials(const Mat &featureVector, Mat &potential, Mat &mask) const
Calculates the node potential, based on the feature vector.
virtual ~CTrainNodeGMM(void)
std::vector< CKDGauss > GaussianMixture
TrainNodeGMMParams m_params
const TrainNodeGMMParams TRAIN_NODE_GMM_PARAMS_DEFAULT
Base abstract class for node potentials training.
double dist_Mtreshold
Minimum Mahalanobis distance between Gauss functions. If this parameter is negative, the Euclidean distance is used.
std::vector< GaussianMixture > m_vGaussianMixtures
Multivariate Gaussian distribution class.
size_t minSamples
Minimum number of sapmles to approximate a Gauss function.
void addFeatureVec(const Mat &featureVector, byte gt)
Adds new feature vector.
byte m_nStates
The number of states (classes)
void loadFile(FILE *pFile)
Loads the random model from the file.