From c9f51d5eed07dbfe803c12a6b97f86bf662f2b21 Mon Sep 17 00:00:00 2001 From: Firat Kalaycilar Date: Fri, 21 Mar 2014 09:44:11 +0200 Subject: [PATCH 1/2] modified BackgroundSubtractorMOG2::getBackgroundImage so that it can now work with gray-level images. --- modules/video/src/bgfg_gaussmix2.cpp | 53 +++++++++++++--------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index b14bc8e1e..ddc8e64bd 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -577,54 +577,49 @@ void BackgroundSubtractorMOG2::operator()(InputArray _image, OutputArray _fgmask void BackgroundSubtractorMOG2::getBackgroundImage(OutputArray backgroundImage) const { int nchannels = CV_MAT_CN(frameType); - CV_Assert( nchannels == 3 ); - Mat meanBackground(frameSize, CV_8UC3, Scalar::all(0)); - + CV_Assert(nchannels == 1 || nchannels == 3); + Mat meanBackground(frameSize, CV_MAKETYPE(CV_8U, nchannels), Scalar::all(0)); int firstGaussianIdx = 0; const GMM* gmm = (GMM*)bgmodel.data; - const Vec3f* mean = reinterpret_cast(gmm + frameSize.width*frameSize.height*nmixtures); + const float* mean = reinterpret_cast(gmm + frameSize.width*frameSize.height*nmixtures); for(int row=0; row(row, col); - Vec3f meanVal; + std::vector meanVal(nchannels, 0.f); float totalWeight = 0.f; for(int gaussianIdx = firstGaussianIdx; gaussianIdx < firstGaussianIdx + nmodes; gaussianIdx++) { GMM gaussian = gmm[gaussianIdx]; - meanVal += gaussian.weight * mean[gaussianIdx]; + size_t meanPosition = gaussianIdx*nchannels; + for(int chn = 0; chn < nchannels; chn++) + { + meanVal[chn] += gaussian.weight * mean[meanPosition + chn]; + } totalWeight += gaussian.weight; if(totalWeight > backgroundRatio) break; } - - meanVal *= (1.f / totalWeight); - meanBackground.at(row, col) = Vec3b(meanVal); + float invWeight = 1.f/totalWeight; + for(int chn = 0; chn < nchannels; chn++) + { + meanVal[chn] *= invWeight; + } + switch(nchannels) + { + case 1: + meanBackground.at(row, col) = (uchar)meanVal[0]; + break; + case 3: + meanBackground.at(row, col) = Vec3b(*reinterpret_cast(&meanVal[0])); + break; + } firstGaussianIdx += nmixtures; } } - - switch(CV_MAT_CN(frameType)) - { - case 1: - { - vector channels; - split(meanBackground, channels); - channels[0].copyTo(backgroundImage); - break; - } - - case 3: - { - meanBackground.copyTo(backgroundImage); - break; - } - - default: - CV_Error(CV_StsUnsupportedFormat, ""); - } + meanBackground.copyTo(backgroundImage); } } From 990295644e4260656787172f959a676bdc0a1066 Mon Sep 17 00:00:00 2001 From: Firat Kalaycilar Date: Tue, 8 Apr 2014 16:10:32 +0300 Subject: [PATCH 2/2] made a performance improvement. changed the way the mean value for each pixel is assigned in the output image. --- modules/video/src/bgfg_gaussmix2.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index ddc8e64bd..9700dfebd 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -582,12 +582,12 @@ void BackgroundSubtractorMOG2::getBackgroundImage(OutputArray backgroundImage) c int firstGaussianIdx = 0; const GMM* gmm = (GMM*)bgmodel.data; const float* mean = reinterpret_cast(gmm + frameSize.width*frameSize.height*nmixtures); + std::vector meanVal(nchannels, 0.f); for(int row=0; row(row, col); - std::vector meanVal(nchannels, 0.f); float totalWeight = 0.f; for(int gaussianIdx = firstGaussianIdx; gaussianIdx < firstGaussianIdx + nmodes; gaussianIdx++) { @@ -603,17 +603,16 @@ void BackgroundSubtractorMOG2::getBackgroundImage(OutputArray backgroundImage) c break; } float invWeight = 1.f/totalWeight; - for(int chn = 0; chn < nchannels; chn++) - { - meanVal[chn] *= invWeight; - } switch(nchannels) { case 1: - meanBackground.at(row, col) = (uchar)meanVal[0]; + meanBackground.at(row, col) = (uchar)(meanVal[0] * invWeight); + meanVal[0] = 0.f; break; case 3: - meanBackground.at(row, col) = Vec3b(*reinterpret_cast(&meanVal[0])); + Vec3f& meanVec = *reinterpret_cast(&meanVal[0]); + meanBackground.at(row, col) = Vec3b(meanVec * invWeight); + meanVec = 0.f; break; } firstGaussianIdx += nmixtures;