title: OpenCV using k-means to posterize an image
body: <p>I want to posterize an image with k-means and OpenCV in C++ interface (cv namespace) and I get weird results. I need it for reduce some noise. This is my code:</p>
  <pre><code>#include &quot;cv.h&quot;
  #include &quot;highgui.h&quot;
  
  using namespace cv;
  
  int main() {
      Mat imageBGR, imageHSV, planeH, planeS, planeV;
  
      imageBGR = imread(&quot;fruits.jpg&quot;);
      imshow(&quot;original&quot;, imageBGR);
      
      cv::Mat labels, data;
      cv::Mat centers(8, 1, CV_32FC1);
      imageBGR.convertTo(data, CV_32F);
  
      cv::kmeans(data, 8, labels,
              cv::TermCriteria(CV_TERMCRIT_ITER, 10, 1.0),
              3, cv::KMEANS_PP_CENTERS, &amp;centers);
      imshow(&quot;posterized hue&quot;, data);
      data.convertTo(data, CV_32FC3);
  
      waitKey();
      return 0;
  }
  </code></pre>
  <p>But I get a weird result</p>
  <p><img src="https://i.stack.imgur.com/dGy2i.png" alt="Fruit" /></p>
  <p>First image: original</p>
  <p>Second image: after k-means.</p>
  <p>Any advice?</p>
  <hr />
  <h1>Update: the right solution. maybe someone can help me in optimize the code?</h1>
  <pre><code>#include &quot;cv.h&quot;
  #include &quot;highgui.h&quot;
  
  #include &lt;iostream&gt;
  
  using namespace cv;
  using namespace std;
  
  int main() {
      Mat src;
  
      src = imread(&quot;fruits.jpg&quot;);
      imshow(&quot;original&quot;, src);
  
      blur(src, src, Size(15,15));
      imshow(&quot;blurred&quot;, src);
  
      Mat p = Mat::zeros(src.cols*src.rows, 5, CV_32F);
      Mat bestLabels, centers, clustered;
      vector&lt;Mat&gt; bgr;
      cv::split(src, bgr);
      // i think there is a better way to split pixel bgr color
      for(int i=0; i&lt;src.cols*src.rows; i++) {
          p.at&lt;float&gt;(i,0) = (i/src.cols) / src.rows;
          p.at&lt;float&gt;(i,1) = (i%src.cols) / src.cols;
          p.at&lt;float&gt;(i,2) = bgr[0].data[i] / 255.0;
          p.at&lt;float&gt;(i,3) = bgr[1].data[i] / 255.0;
          p.at&lt;float&gt;(i,4) = bgr[2].data[i] / 255.0;
      }
  
      int K = 8;
      cv::kmeans(p, K, bestLabels,
              TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0),
              3, KMEANS_PP_CENTERS, centers);
  
      int colors[K];
      for(int i=0; i&lt;K; i++) {
          colors[i] = 255/(i+1);
      }
      // i think there is a better way to do this mayebe some Mat::reshape?
      clustered = Mat(src.rows, src.cols, CV_32F);
      for(int i=0; i&lt;src.cols*src.rows; i++) {
          clustered.at&lt;float&gt;(i/src.cols, i%src.cols) = (float)(colors[bestLabels.at&lt;int&gt;(0,i)]);
  //      cout &lt;&lt; bestLabels.at&lt;int&gt;(0,i) &lt;&lt; &quot; &quot; &lt;&lt; 
  //              colors[bestLabels.at&lt;int&gt;(0,i)] &lt;&lt; &quot; &quot; &lt;&lt; 
  //              clustered.at&lt;float&gt;(i/src.cols, i%src.cols) &lt;&lt; &quot; &quot; &lt;&lt;
  //              endl;
      }
  
      clustered.convertTo(clustered, CV_8U);
      imshow(&quot;clustered&quot;, clustered);
  
      waitKey();
      return 0;
  }
  </code></pre>
  <p>Result:</p>
  <p><img src="https://i.stack.imgur.com/QBVcV.png" alt="Posterized Fruit" /></p>