diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 2d61b381c5..210126b427 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -2428,6 +2428,41 @@ static void generateRandomCenter(const vector& box, float* center, RNG& r center[j] = ((float)rng*(1.f+margin*2.f)-margin)*(box[j][1] - box[j][0]) + box[j][0]; } +class KMeansPPDistanceComputer +{ +public: + KMeansPPDistanceComputer( float *_tdist2, + const float *_data, + const float *_dist, + int _dims, + size_t _step, + size_t _stepci ) + : tdist2(_tdist2), + data(_data), + dist(_dist), + dims(_dims), + step(_step), + stepci(_stepci) { } + + void operator()( const cv::BlockedRange& range ) const + { + const int begin = range.begin(); + const int end = range.end(); + + for ( int i = begin; i(i); + int k_best = 0; + double min_dist = DBL_MAX; + + for( int k = 0; k < K; k++ ) + { + const float* center = centers.ptr(k); + const double dist = normL2Sqr_(sample, center, dims); + + if( min_dist > dist ) + { + min_dist = dist; + k_best = k; + } + } + + distances[i] = min_dist; + labels[i] = k_best; + } + } + +private: + double *distances; + int *labels; + const Mat& data; + const Mat& centers; +}; + } double cv::kmeans( InputArray _data, int K, @@ -2536,7 +2626,6 @@ double cv::kmeans( InputArray _data, int K, vector counters(K); vector _box(dims); Vec2f* box = &_box[0]; - double best_compactness = DBL_MAX, compactness = 0; RNG& rng = theRNG(); int a, iter, i, j, k; @@ -2711,27 +2800,14 @@ double cv::kmeans( InputArray _data, int K, break; // assign labels + Mat dists(1, N, CV_64F); + double* dist = dists.ptr(0); + parallel_for(BlockedRange(0, N), + KMeansDistanceComputer(dist, labels, data, centers)); compactness = 0; for( i = 0; i < N; i++ ) { - sample = data.ptr(i); - int k_best = 0; - double min_dist = DBL_MAX; - - for( k = 0; k < K; k++ ) - { - const float* center = centers.ptr(k); - double dist = normL2Sqr_(sample, center, dims); - - if( min_dist > dist ) - { - min_dist = dist; - k_best = k; - } - } - - compactness += min_dist; - labels[i] = k_best; + compactness += dist[i]; } }