mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
Fix #27968: Eliminate unnecessary type conversions in GrabCut initGMMs
Remove performance bottleneck caused by redundant type conversions in the initGMMs() function's tight nested loops that iterate over all image pixels. Changes: - Changed storage vectors from Vec3f to Vec3b to store pixel data directly without intermediate conversion - Modified kmeans preparation to convert Vec3b data to CV_32FC1 only when creating the Mat for clustering (using convertTo instead of per-pixel cast) - Explicitly convert Vec3b to Vec3d only when calling addSample() method Performance Impact: Previously: Vec3b -> Vec3f (in loop) -> Vec3d (implicit in addSample) Now: Vec3b (in loop) -> Vec3d (explicit, only in addSample call) This eliminates one unnecessary type conversion per pixel in the tight loop, reducing computational overhead especially for large images. Fixes #27968
This commit is contained in:
@@ -371,28 +371,30 @@ static void initGMMs( const Mat& img, const Mat& mask, GMM& bgdGMM, GMM& fgdGMM
|
||||
const int kMeansType = KMEANS_PP_CENTERS;
|
||||
|
||||
Mat bgdLabels, fgdLabels;
|
||||
std::vector<Vec3f> bgdSamples, fgdSamples;
|
||||
std::vector<Vec3b> bgdSamples, fgdSamples;
|
||||
Point p;
|
||||
for( p.y = 0; p.y < img.rows; p.y++ )
|
||||
{
|
||||
for( p.x = 0; p.x < img.cols; p.x++ )
|
||||
{
|
||||
if( mask.at<uchar>(p) == GC_BGD || mask.at<uchar>(p) == GC_PR_BGD )
|
||||
bgdSamples.push_back( (Vec3f)img.at<Vec3b>(p) );
|
||||
bgdSamples.push_back( img.at<Vec3b>(p) );
|
||||
else // GC_FGD | GC_PR_FGD
|
||||
fgdSamples.push_back( (Vec3f)img.at<Vec3b>(p) );
|
||||
fgdSamples.push_back( img.at<Vec3b>(p) );
|
||||
}
|
||||
}
|
||||
CV_Assert( !bgdSamples.empty() && !fgdSamples.empty() );
|
||||
{
|
||||
Mat _bgdSamples( (int)bgdSamples.size(), 3, CV_32FC1, &bgdSamples[0][0] );
|
||||
Mat _bgdSamples( (int)bgdSamples.size(), 3, CV_8UC1, &bgdSamples[0][0] );
|
||||
_bgdSamples.convertTo(_bgdSamples, CV_32FC1);
|
||||
int num_clusters = GMM::componentsCount;
|
||||
num_clusters = std::min(num_clusters, (int)bgdSamples.size());
|
||||
kmeans( _bgdSamples, num_clusters, bgdLabels,
|
||||
TermCriteria( TermCriteria::MAX_ITER, kMeansItCount, 0.0), 0, kMeansType );
|
||||
}
|
||||
{
|
||||
Mat _fgdSamples( (int)fgdSamples.size(), 3, CV_32FC1, &fgdSamples[0][0] );
|
||||
Mat _fgdSamples( (int)fgdSamples.size(), 3, CV_8UC1, &fgdSamples[0][0] );
|
||||
_fgdSamples.convertTo(_fgdSamples, CV_32FC1);
|
||||
int num_clusters = GMM::componentsCount;
|
||||
num_clusters = std::min(num_clusters, (int)fgdSamples.size());
|
||||
kmeans( _fgdSamples, num_clusters, fgdLabels,
|
||||
@@ -401,12 +403,12 @@ static void initGMMs( const Mat& img, const Mat& mask, GMM& bgdGMM, GMM& fgdGMM
|
||||
|
||||
bgdGMM.initLearning();
|
||||
for( int i = 0; i < (int)bgdSamples.size(); i++ )
|
||||
bgdGMM.addSample( bgdLabels.at<int>(i,0), bgdSamples[i] );
|
||||
bgdGMM.addSample( bgdLabels.at<int>(i,0), Vec3d(bgdSamples[i]) );
|
||||
bgdGMM.endLearning();
|
||||
|
||||
fgdGMM.initLearning();
|
||||
for( int i = 0; i < (int)fgdSamples.size(); i++ )
|
||||
fgdGMM.addSample( fgdLabels.at<int>(i,0), fgdSamples[i] );
|
||||
fgdGMM.addSample( fgdLabels.at<int>(i,0), Vec3d(fgdSamples[i]) );
|
||||
fgdGMM.endLearning();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user