added TBB for kmeans (patch #1261: thanks to Boris Mansencal)
This commit is contained in:
@@ -2428,6 +2428,41 @@ static void generateRandomCenter(const vector<Vec2f>& box, float* center, RNG& r
|
|||||||
center[j] = ((float)rng*(1.f+margin*2.f)-margin)*(box[j][1] - box[j][0]) + box[j][0];
|
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<end; i++ )
|
||||||
|
{
|
||||||
|
tdist2[i] = std::min(normL2Sqr_(data + step*i, data + stepci, dims), dist[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
float *tdist2;
|
||||||
|
const float *data;
|
||||||
|
const float *dist;
|
||||||
|
const int dims;
|
||||||
|
const size_t step;
|
||||||
|
const size_t stepci;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
k-means center initialization using the following algorithm:
|
k-means center initialization using the following algorithm:
|
||||||
@@ -2465,9 +2500,11 @@ static void generateCentersPP(const Mat& _data, Mat& _out_centers,
|
|||||||
if( (p -= dist[i]) <= 0 )
|
if( (p -= dist[i]) <= 0 )
|
||||||
break;
|
break;
|
||||||
int ci = i;
|
int ci = i;
|
||||||
|
|
||||||
|
parallel_for(BlockedRange(0, N),
|
||||||
|
KMeansPPDistanceComputer(tdist2, data, dist, dims, step, step*ci));
|
||||||
for( i = 0; i < N; i++ )
|
for( i = 0; i < N; i++ )
|
||||||
{
|
{
|
||||||
tdist2[i] = std::min(normL2Sqr_(data + step*i, data + step*ci, dims), dist[i]);
|
|
||||||
s += tdist2[i];
|
s += tdist2[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2492,6 +2529,59 @@ static void generateCentersPP(const Mat& _data, Mat& _out_centers,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class KMeansDistanceComputer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KMeansDistanceComputer( double *_distances,
|
||||||
|
int *_labels,
|
||||||
|
const Mat& _data,
|
||||||
|
const Mat& _centers )
|
||||||
|
: distances(_distances),
|
||||||
|
labels(_labels),
|
||||||
|
data(_data),
|
||||||
|
centers(_centers)
|
||||||
|
{
|
||||||
|
CV_DbgAssert(centers.cols == data.cols);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()( const BlockedRange& range ) const
|
||||||
|
{
|
||||||
|
const int begin = range.begin();
|
||||||
|
const int end = range.end();
|
||||||
|
const int K = centers.rows;
|
||||||
|
const int dims = centers.cols;
|
||||||
|
|
||||||
|
const float *sample;
|
||||||
|
for( int i = begin; i<end; ++i)
|
||||||
|
{
|
||||||
|
sample = data.ptr<float>(i);
|
||||||
|
int k_best = 0;
|
||||||
|
double min_dist = DBL_MAX;
|
||||||
|
|
||||||
|
for( int k = 0; k < K; k++ )
|
||||||
|
{
|
||||||
|
const float* center = centers.ptr<float>(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,
|
double cv::kmeans( InputArray _data, int K,
|
||||||
@@ -2536,7 +2626,6 @@ double cv::kmeans( InputArray _data, int K,
|
|||||||
vector<int> counters(K);
|
vector<int> counters(K);
|
||||||
vector<Vec2f> _box(dims);
|
vector<Vec2f> _box(dims);
|
||||||
Vec2f* box = &_box[0];
|
Vec2f* box = &_box[0];
|
||||||
|
|
||||||
double best_compactness = DBL_MAX, compactness = 0;
|
double best_compactness = DBL_MAX, compactness = 0;
|
||||||
RNG& rng = theRNG();
|
RNG& rng = theRNG();
|
||||||
int a, iter, i, j, k;
|
int a, iter, i, j, k;
|
||||||
@@ -2711,27 +2800,14 @@ double cv::kmeans( InputArray _data, int K,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
// assign labels
|
// assign labels
|
||||||
|
Mat dists(1, N, CV_64F);
|
||||||
|
double* dist = dists.ptr<double>(0);
|
||||||
|
parallel_for(BlockedRange(0, N),
|
||||||
|
KMeansDistanceComputer(dist, labels, data, centers));
|
||||||
compactness = 0;
|
compactness = 0;
|
||||||
for( i = 0; i < N; i++ )
|
for( i = 0; i < N; i++ )
|
||||||
{
|
{
|
||||||
sample = data.ptr<float>(i);
|
compactness += dist[i];
|
||||||
int k_best = 0;
|
|
||||||
double min_dist = DBL_MAX;
|
|
||||||
|
|
||||||
for( k = 0; k < K; k++ )
|
|
||||||
{
|
|
||||||
const float* center = centers.ptr<float>(k);
|
|
||||||
double dist = normL2Sqr_(sample, center, dims);
|
|
||||||
|
|
||||||
if( min_dist > dist )
|
|
||||||
{
|
|
||||||
min_dist = dist;
|
|
||||||
k_best = k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
compactness += min_dist;
|
|
||||||
labels[i] = k_best;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user