Ask Your Question

Revision history [back]

for color quantization without number of color you can use cvPyrMeanShift else quantization with number of color you can use cvKmean.In the KMean method the number of clusters is equal to number of the output colors and convert the input image rows/columns as a set of 1D vectors with 3 component(RGB).You have to use KMean in 3D instead of 2D. For quantization by KMean use the below code.

void bhQuantizeImage(IplImage* srcImage,IplImage* dstImage,int colorCount)
{
     int i, size;

  CvMat *clusters;
  CvMat *points;
  CvMat *color = cvCreateMat (colorCount, 1, CV_32FC3);
  CvMat *count = cvCreateMat (colorCount, 1, CV_32SC1);


  size = srcImage->width * srcImage->height;
  dstImage = cvCloneImage (srcImage);
  clusters = cvCreateMat (size, 1, CV_32SC1);
  points = cvCreateMat (size, 1, CV_32FC3);

  for (i = 0; i < size; i++) {
    points->data.fl[i * 3 + 0] = (uchar) srcImage->imageData[i * 3 + 0];
    points->data.fl[i * 3 + 1] = (uchar) srcImage->imageData[i * 3 + 1];
    points->data.fl[i * 3 + 2] = (uchar) srcImage->imageData[i * 3 + 2];
  }

  cvKMeans2 (points, colorCount, clusters, cvTermCriteria (CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0));

  cvSetZero (color);
  cvSetZero (count);
  for (i = 0; i < size; i++) {
    int idx = clusters->data.i[i];
    int j = ++count->data.i[idx];;
    color->data.fl[idx * 3 + 0] = color->data.fl[idx * 3 + 0] * (j - 1) / j + points->data.fl[i * 3 + 0] / j;
    color->data.fl[idx * 3 + 1] = color->data.fl[idx * 3 + 1] * (j - 1) / j + points->data.fl[i * 3 + 1] / j;
    color->data.fl[idx * 3 + 2] = color->data.fl[idx * 3 + 2] * (j - 1) / j + points->data.fl[i * 3 + 2] / j;
  }

  for (i = 0; i < size; i++) {
    int idx = clusters->data.i[i];
    dstImage->imageData[i * 3 + 0] = (char) color->data.fl[idx * 3 + 0];
    dstImage->imageData[i * 3 + 1] = (char) color->data.fl[idx * 3 + 1];
    dstImage->imageData[i * 3 + 2] = (char) color->data.fl[idx * 3 + 2];
  }


  cvReleaseImage (&srcImage);
  cvReleaseImage (&dstImage);
  cvReleaseMat (&clusters);
  cvReleaseMat (&points);
  cvReleaseMat (&color);
  cvReleaseMat (&count);
}

for color quantization without number of color you can use cvPyrMeanShift else quantization with number of color you can use cvKmean.In the KMean method the number of clusters is equal to number of the output colors and convert the input image rows/columns as a set of 1D vectors with 3 component(RGB).You have to use KMean in 3D instead of 2D. For quantization by KMean use the below code.

void bhQuantizeImage(IplImage* srcImage,IplImage* dstImage,int colorCount)
{
     int i, size;

  CvMat *clusters;
  CvMat *points;
  CvMat *color = cvCreateMat (colorCount, 1, CV_32FC3);
  CvMat *count = cvCreateMat (colorCount, 1, CV_32SC1);


  size = srcImage->width * srcImage->height;
  dstImage = cvCloneImage (srcImage);
  clusters = cvCreateMat (size, 1, CV_32SC1);
  points = cvCreateMat (size, 1, CV_32FC3);

  for (i = 0; i < size; i++) {
    points->data.fl[i * 3 + 0] = (uchar) srcImage->imageData[i * 3 + 0];
    points->data.fl[i * 3 + 1] = (uchar) srcImage->imageData[i * 3 + 1];
    points->data.fl[i * 3 + 2] = (uchar) srcImage->imageData[i * 3 + 2];
  }

  cvKMeans2 (points, colorCount, clusters, cvTermCriteria (CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0));

  cvSetZero (color);
  cvSetZero (count);
  for (i = 0; i < size; i++) {
    int idx = clusters->data.i[i];
    int j = ++count->data.i[idx];;
    color->data.fl[idx * 3 + 0] = color->data.fl[idx * 3 + 0] * (j - 1) / j + points->data.fl[i * 3 + 0] / j;
    color->data.fl[idx * 3 + 1] = color->data.fl[idx * 3 + 1] * (j - 1) / j + points->data.fl[i * 3 + 1] / j;
    color->data.fl[idx * 3 + 2] = color->data.fl[idx * 3 + 2] * (j - 1) / j + points->data.fl[i * 3 + 2] / j;
  }

  for (i = 0; i < size; i++) {
    int idx = clusters->data.i[i];
    dstImage->imageData[i * 3 + 0] = (char) color->data.fl[idx * 3 + 0];
    dstImage->imageData[i * 3 + 1] = (char) color->data.fl[idx * 3 + 1];
    dstImage->imageData[i * 3 + 2] = (char) color->data.fl[idx * 3 + 2];
  }


  cvReleaseImage (&srcImage);
  cvReleaseImage (&dstImage);
  cvReleaseMat (&clusters);
  cvReleaseMat (&points);
  cvReleaseMat (&color);
  cvReleaseMat (&count);
}