First time here? Check out the FAQ!

Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

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);
}
click to hide/show revision 2
No.2 Revision

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);
}