diff --git a/modules/flann/include/opencv2/flann/kmeans_index.h b/modules/flann/include/opencv2/flann/kmeans_index.h
index 74bbf400c3..fe91dddd16 100644
--- a/modules/flann/include/opencv2/flann/kmeans_index.h
+++ b/modules/flann/include/opencv2/flann/kmeans_index.h
@@ -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