Ask Your Question
1

Colour Quantization

asked Dec 18 '12

imran gravatar image

updated Apr 13 '16

LBerger gravatar image

Does anyone know if there are any Colour Quantization (Colour Reduction) methods in OpenCV?

If so, could you please guide me to where it is? Or anyone else that has implemented it using OpenCV?

Preview: (hide)

2 answers

Sort by » oldest newest most voted
3

answered Dec 19 '12

updated Dec 19 '12

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


  cvReleaseMat (&clusters);
  cvReleaseMat (&points);
  cvReleaseMat (&color);
  cvReleaseMat (&count);
}
Preview: (hide)

Comments

Thanks for the guidance.

imran gravatar imageimran (Dec 20 '12)edit

Thanks for the detailed answer. If possible though; can some documentation be added to the code to highlight the key tasks for further elaboration?

user1446598 gravatar imageuser1446598 (Mar 31 '13)edit
1

answered Dec 18 '12

SR gravatar image

Choose k-colors by using k-means clustering

Preview: (hide)

Comments

Thanks for the guidance

imran gravatar imageimran (Dec 20 '12)edit

Question Tools

1 follower

Stats

Asked: Dec 18 '12

Seen: 6,740 times

Last updated: Dec 19 '12