@ -276,17 +276,15 @@ public:
public :
KMeansDistanceComputer ( Distance _distance , const Matrix < ElementType > & _dataset ,
const int _branching , const int * _indices , const Matrix < double > & _dcenters , const size_t _veclen ,
int * _count , int * _belongs_to , std : : vector < DistanceType > & _radiuses , bool & _converged )
std : : vector < int > & _new_centroids , std : : vector < DistanceType > & _sq_dists )
: distance ( _distance )
, dataset ( _dataset )
, branching ( _branching )
, indices ( _indices )
, dcenters ( _dcenters )
, veclen ( _veclen )
, count ( _count )
, belongs_to ( _belongs_to )
, radiuses ( _radiuses )
, converged ( _converged )
, new_centroids ( _new_centroids )
, sq_dists ( _sq_dists )
{
}
@ -297,8 +295,8 @@ public:
for ( int i = begin ; i < end ; + + i )
{
DistanceType sq_dist = distance ( dataset [ indices [ i ] ] , dcenters [ 0 ] , veclen ) ;
int new_centroid = 0 ;
DistanceType sq_dist ( distance ( dataset [ indices [ i ] ] , dcenters [ 0 ] , veclen ) ) ;
int new_centroid ( 0 ) ;
for ( int j = 1 ; j < branching ; + + j ) {
DistanceType new_sq_dist = distance ( dataset [ indices [ i ] ] , dcenters [ j ] , veclen ) ;
if ( sq_dist > new_sq_dist ) {
@ -306,15 +304,8 @@ public:
sq_dist = new_sq_dist ;
}
}
if ( sq_dist > radiuses [ new_centroid ] ) {
radiuses [ new_centroid ] = sq_dist ;
}
if ( new_centroid ! = belongs_to [ i ] ) {
CV_XADD ( & count [ belongs_to [ i ] ] , - 1 ) ;
CV_XADD ( & count [ new_centroid ] , 1 ) ;
belongs_to [ i ] = new_centroid ;
converged = false ;
}
sq_dists [ i ] = sq_dist ;
new_centroids [ i ] = new_centroid ;
}
}
@ -325,10 +316,8 @@ public:
const int * indices ;
const Matrix < double > & dcenters ;
const size_t veclen ;
int * count ;
int * belongs_to ;
std : : vector < DistanceType > & radiuses ;
bool & converged ;
std : : vector < int > & new_centroids ;
std : : vector < DistanceType > & sq_dists ;
KMeansDistanceComputer & operator = ( const KMeansDistanceComputer & ) { return * this ; }
} ;
@ -796,10 +785,27 @@ private:
}
}
std : : vector < int > new_centroids ( indices_length ) ;
std : : vector < DistanceType > sq_dists ( indices_length ) ;
// reassign points to clusters
KMeansDistanceComputer invoker ( distance_ , dataset_ , branching , indices , dcenters , veclen_ , count , belongs_to , radiuses , converged ) ;
KMeansDistanceComputer invoker ( distance_ , dataset_ , branching , indices , dcenters , veclen_ , new_centroids , sq_dists ) ;
parallel_for_ ( cv : : Range ( 0 , ( int ) indices_length ) , invoker ) ;
for ( int i = 0 ; i < ( int ) indices_length ; + + i ) {
DistanceType sq_dist ( sq_dists [ i ] ) ;
int new_centroid ( new_centroids [ i ] ) ;
if ( sq_dist > radiuses [ new_centroid ] ) {
radiuses [ new_centroid ] = sq_dist ;
}
if ( new_centroid ! = belongs_to [ i ] ) {
count [ belongs_to [ i ] ] - - ;
count [ new_centroid ] + + ;
belongs_to [ i ] = new_centroid ;
converged = false ;
}
}
for ( int i = 0 ; i < branching ; + + i ) {
// if one cluster converges to an empty cluster,
// move an element into that cluster