Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find dominant color on an image

I want to find dominant color on an image. For this, I know that I should use image histogram. But I am not sure of image format. Which one of rgb, hsv or gray image, should be used?

After the histogram is calculated, I should find max value on histogram. For this, should I find below maximum binVal value for hsv image? Why my result image contains only black color?

float binVal = hist.at<float>(h, s);

EDIT :

I have tried the below code. I draw h-s histogram. And my result images are here. I don't find anything after binary threshold. Maybe I find max histogram value incorrectly.

enter image description hereenter image description here

cvtColor(src, hsv, CV_BGR2HSV);

// Quantize the hue to 30 levels
// and the saturation to 32 levels
int hbins = 20, sbins = 22;
int histSize[] = {hbins, sbins};
// hue varies from 0 to 179, see cvtColor
float hranges[] = { 0, 180 };
// saturation varies from 0 (black-gray-white) to
// 255 (pure spectrum color)
float sranges[] = { 0, 256 };
const float* ranges[] = { hranges, sranges };
MatND hist;
// we compute the histogram from the 0-th and 1-st channels
int channels[] = {0, 1};

calcHist( &hsv, 1, channels, Mat(), // do not use mask
         hist, 2, histSize, ranges,
         true, // the histogram is uniform
         false );
double maxVal=0;
minMaxLoc(hist, 0, &maxVal, 0, 0);

int scale = 10;
Mat histImg = Mat::zeros(sbins*scale, hbins*10, CV_8UC3);
int maxIntensity = -100;
for( int h = 0; h < hbins; h++ ) {
    for( int s = 0; s < sbins; s++ )
    {
        float binVal = hist.at<float>(h, s);
        int intensity = cvRound(binVal*255/maxVal);
        rectangle( histImg, Point(h*scale, s*scale),
                    Point( (h+1)*scale - 1, (s+1)*scale - 1),
                    Scalar::all(intensity),
                    CV_FILLED );
        if(intensity > maxIntensity)
            maxIntensity = intensity;
    }
}
std::cout << "max Intensity " << maxVal << std::endl;
Mat dst;
cv::threshold(src, dst, maxIntensity, 255, cv::THRESH_BINARY);

namedWindow( "Dest", 1 );
imshow( "Dest", dst );
namedWindow( "Source", 1 );
imshow( "Source", src );

namedWindow( "H-S Histogram", 1 );
imshow( "H-S Histogram", histImg );
like image 555
zakjma Avatar asked Mar 01 '15 13:03

zakjma


People also ask

What color is dominant in the picture?

Understand Dominant And Receding Colors In photography, the dominant colors are the warm colors, e.g. red, yellow, and orange. These colors are considered dominant because they reach our eyes before the cooler colors. The cooler colors are the receding colors, e.g. blue, green and purple.

How do I determine my dominant color?

The most important thing to remember when determining dominant and recessive colors is that dominant colors always stand out. On a photograph, poster, or sign, a dominant color creates a single point of focus. Simply put, it is the spot that draws your attention. In contrast, recessive colors blend into the background.

How do you extract the dominant color from an image in Python?

Dominant colors are displayed using imshow() method, which takes RGB values scaled to the range of 0 to 1. To do so, you need to multiply the standardized values of the cluster centers with there corresponding standard deviations.


2 Answers

Alternatively you could try a k-means approach. Calculate k clusters with k ~ 2..5 and take the centroid of the biggest group as your dominant color.

The python docu of OpenCv has an illustrated example that gets the dominant color(s) pretty well:

like image 75
mbschenkel Avatar answered Sep 21 '22 12:09

mbschenkel


The solution

  • Find H-S histogram
  • Find peak H value(using minmaxLoc function)
  • Split image 3 channel(h,s,v)
  • Apply to threshold.
  • Create image by merge 3 channel
like image 41
zakjma Avatar answered Sep 17 '22 12:09

zakjma