| 172 | } |
| 173 | |
| 174 | void GMM::endLearning() |
| 175 | { |
| 176 | const double variance = 0.01; |
| 177 | for( int ci = 0; ci < componentsCount; ci++ ) |
| 178 | { |
| 179 | int n = sampleCounts[ci]; |
| 180 | if( n == 0 ) |
| 181 | coefs[ci] = 0; |
| 182 | else |
| 183 | { |
| 184 | coefs[ci] = (double)n/totalSampleCount; |
| 185 | |
| 186 | double* m = mean + 3*ci; |
| 187 | m[0] = sums[ci][0]/n; m[1] = sums[ci][1]/n; m[2] = sums[ci][2]/n; |
| 188 | |
| 189 | double* c = cov + 9*ci; |
| 190 | c[0] = prods[ci][0][0]/n - m[0]*m[0]; c[1] = prods[ci][0][1]/n - m[0]*m[1]; c[2] = prods[ci][0][2]/n - m[0]*m[2]; |
| 191 | c[3] = prods[ci][1][0]/n - m[1]*m[0]; c[4] = prods[ci][1][1]/n - m[1]*m[1]; c[5] = prods[ci][1][2]/n - m[1]*m[2]; |
| 192 | c[6] = prods[ci][2][0]/n - m[2]*m[0]; c[7] = prods[ci][2][1]/n - m[2]*m[1]; c[8] = prods[ci][2][2]/n - m[2]*m[2]; |
| 193 | |
| 194 | double dtrm = c[0]*(c[4]*c[8]-c[5]*c[7]) - c[1]*(c[3]*c[8]-c[5]*c[6]) + c[2]*(c[3]*c[7]-c[4]*c[6]); |
| 195 | if( dtrm <= std::numeric_limits<double>::epsilon() ) |
| 196 | { |
| 197 | // Adds the white noise to avoid singular covariance matrix. |
| 198 | c[0] += variance; |
| 199 | c[4] += variance; |
| 200 | c[8] += variance; |
| 201 | } |
| 202 | |
| 203 | calcInverseCovAndDeterm(ci); |
| 204 | } |
| 205 | } |
| 206 | } |
| 207 | |
| 208 | void GMM::calcInverseCovAndDeterm( int ci ) |
| 209 | { |