From 762cf182ef2545d15c861a45d4e4f1a42732a996 Mon Sep 17 00:00:00 2001 From: Maria Dimashova Date: Thu, 11 Nov 2010 12:04:40 +0000 Subject: [PATCH] modified grabCut: noise is added only if covariance determinant = 0 --- modules/imgproc/src/grabcut.cpp | 50 ++++++++++++----------------------------- 1 file changed, 14 insertions(+), 36 deletions(-) diff --git a/modules/imgproc/src/grabcut.cpp b/modules/imgproc/src/grabcut.cpp index a60508a..d224475 100644 --- a/modules/imgproc/src/grabcut.cpp +++ b/modules/imgproc/src/grabcut.cpp @@ -51,35 +51,6 @@ This is implementation of image segmentation algorithm GrabCut described in Carsten Rother, Vladimir Kolmogorov, Andrew Blake. */ -class Noise3DGenerator -{ -public: - Noise3DGenerator( float var=0.1f ) : rng(theRNG()) - { - var = std::min( std::max( 0.01f, var ), 1.f ) ; - - double meanData[] = { 0., 0., 0. }; - double covData[] = { var, 0., 0., - 0., var, 0., - 0., 0., var }; - Mat( 1, 3, CV_64FC1, meanData ).copyTo( mean ); - Mat( 3, 3, CV_64FC1, covData ).copyTo( cov ); - } - - Vec3d generateNoise() - { - Mat noise( 1, 3, CV_64FC1 ); - rng.fill( noise, RNG::NORMAL, Scalar::all(0.0), Scalar(1.0) ); - noise = noise * cov + mean; - return Vec3d( noise.ptr() ); - } - -private: - RNG& rng; - Mat mean; - Mat cov; -}; - /* GMM - Gaussian Mixture Model */ @@ -111,8 +82,6 @@ private: double prods[componentsCount][3][3]; int sampleCounts[componentsCount]; int totalSampleCount; - - Noise3DGenerator noiseGenerator; }; GMM::GMM( Mat& _model ) @@ -194,17 +163,17 @@ void GMM::initLearning() void GMM::addSample( int ci, const Vec3d color ) { - Vec3d nClr = color + noiseGenerator.generateNoise(); - sums[ci][0] += nClr[0]; sums[ci][1] += nClr[1]; sums[ci][2] += nClr[2]; - prods[ci][0][0] += nClr[0]*nClr[0]; prods[ci][0][1] += nClr[0]*nClr[1]; prods[ci][0][2] += nClr[0]*nClr[2]; - prods[ci][1][0] += nClr[1]*nClr[0]; prods[ci][1][1] += nClr[1]*nClr[1]; prods[ci][1][2] += nClr[1]*nClr[2]; - prods[ci][2][0] += nClr[2]*nClr[0]; prods[ci][2][1] += nClr[2]*nClr[1]; prods[ci][2][2] += nClr[2]*nClr[2]; + sums[ci][0] += color[0]; sums[ci][1] += color[1]; sums[ci][2] += color[2]; + prods[ci][0][0] += color[0]*color[0]; prods[ci][0][1] += color[0]*color[1]; prods[ci][0][2] += color[0]*color[2]; + prods[ci][1][0] += color[1]*color[0]; prods[ci][1][1] += color[1]*color[1]; prods[ci][1][2] += color[1]*color[2]; + prods[ci][2][0] += color[2]*color[0]; prods[ci][2][1] += color[2]*color[1]; prods[ci][2][2] += color[2]*color[2]; sampleCounts[ci]++; totalSampleCount++; } void GMM::endLearning() { + const double variance = 0.01; for( int ci = 0; ci < componentsCount; ci++ ) { int n = sampleCounts[ci]; @@ -222,6 +191,15 @@ void GMM::endLearning() 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]; 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]; + 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]); + if( dtrm < std::numeric_limits::epsilon() ) + { + // Adds the white noise to avoid singular covariance matrix. + c[0] += variance; + c[4] += variance; + c[8] += variance; + } + calcInverseCovAndDeterm(ci); } } -- 2.7.4