diff --git a/modules/flann/include/opencv2/flann/kmeans_index.h b/modules/flann/include/opencv2/flann/kmeans_index.h index bfc9b9145..b49b8ddde 100644 --- a/modules/flann/include/opencv2/flann/kmeans_index.h +++ b/modules/flann/include/opencv2/flann/kmeans_index.h @@ -271,6 +271,71 @@ public: return FLANN_INDEX_KMEANS; } + class KMeansDistanceComputer : public cv::ParallelLoopBody + { + public: + KMeansDistanceComputer(Distance _distance, const Matrix& _dataset, + const int _branching, const int* _indices, const Matrix& _dcenters, const size_t _veclen, + int* _count, int* _belongs_to, std::vector& _radiuses, bool& _converged, cv::Mutex& _mtx) + : distance(_distance) + , dataset(_dataset) + , branching(_branching) + , indices(_indices) + , dcenters(_dcenters) + , veclen(_veclen) + , count(_count) + , belongs_to(_belongs_to) + , radiuses(_radiuses) + , converged(_converged) + , mtx(_mtx) + { + } + + void operator()(const cv::Range& range) const + { + const int begin = range.start; + const int end = range.end; + + for( int i = begin; inew_sq_dist) { + new_centroid = j; + sq_dist = new_sq_dist; + } + } + 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; + mtx.lock(); + converged = false; + mtx.unlock(); + } + } + } + + private: + Distance distance; + const Matrix& dataset; + const int branching; + const int* indices; + const Matrix& dcenters; + const size_t veclen; + int* count; + int* belongs_to; + std::vector& radiuses; + bool& converged; + cv::Mutex& mtx; + KMeansDistanceComputer& operator=( const KMeansDistanceComputer & ) { return *this; } + }; + /** * Index constructor * @@ -658,7 +723,8 @@ private: return; } - int* centers_idx = new int[branching]; + cv::AutoBuffer centers_idx_buf(branching); + int* centers_idx = (int*)centers_idx_buf; int centers_length; (this->*chooseCenters)(branching, indices, indices_length, centers_idx, centers_length); @@ -666,29 +732,30 @@ private: node->indices = indices; std::sort(node->indices,node->indices+indices_length); node->childs = NULL; - delete [] centers_idx; return; } - Matrix dcenters(new double[branching*veclen_],branching,veclen_); + cv::AutoBuffer dcenters_buf(branching*veclen_); + Matrix dcenters((double*)dcenters_buf,branching,veclen_); for (int i=0; i radiuses(branching); - int* count = new int[branching]; + cv::AutoBuffer count_buf(branching); + int* count = (int*)count_buf; for (int i=0; i belongs_to_buf(indices_length); + int* belongs_to = (int*)belongs_to_buf; for (int i=0; inew_sq_dist) { - new_centroid = j; - sq_dist = new_sq_dist; - } - } - 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; - } - } + cv::Mutex mtx; + KMeansDistanceComputer invoker(distance_, dataset_, branching, indices, dcenters, veclen_, count, belongs_to, radiuses, converged, mtx); + parallel_for_(cv::Range(0, (int)indices_length), invoker); for (int i=0; ichilds[c],indices+start, end-start, branching, level+1); start=end; } - - delete[] dcenters.data; - delete[] centers; - delete[] count; - delete[] belongs_to; }