Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

I would use CV_BGR2HSV_FULL color conversion to get all colors within the range of 0..255 included . (For your info, the conversionCV_BGR2HSV returns Hue the range of 0..180 included)

// a sample image
cv::Mat src = (cv::Mat_<Vec3b>(3, 3) <<
    Vec3b(0, 0, 0), Vec3b(128, 128, 128), Vec3b(255, 255, 255),
    Vec3b(255, 0, 0),Vec3b(0, 255, 0), Vec3b(0, 0, 255), 
    Vec3b(255, 255, 0), Vec3b(255, 0, 255), Vec3b(0, 255, 255));
CV_Assert(src.type() == CV_8UC3);

cv::Mat hsvFull;
// this returns hue within the range 0..255
cv::cvtColor(src, hsvFull, CV_BGR2HSV_FULL);
vector<uchar> colorsCount(256,0);
Scalar pixel;
uchar color;
int maxColor=0, minColor=INT16_MAX;
// Scan image to count colors
// see http://docs.opencv.org/3.1.0/db/da5/tutorial_how_to_scan_images.html
// for alternative/efficient way to scan images
for (int r = 0; r < hsvFull.rows; r++)
{
    for (int c = 0; c < hsvFull.cols; c++)
    {
        pixel = hsvFull.at<Vec3b>(Point(c, r));
        color = pixel(0);
        colorsCount[color] +=1;
        if (color < minColor) minColor = color;
        if (color > maxColor) maxColor = color;
    }
}
int colorRange = maxColor - minColor;
int minCount, maxCount;
minCount = colorsCount[minColor];
maxCount = colorsCount[maxColor];

If you like you can apply a lookup table to reduce colors to %20

Mat lookUpTable(1, 256, CV_8U);
Mat hsvDiscrete;
uchar* p = lookUpTable.ptr();
for (int i = 0; i < 256; ++i)
    p[i] = i - i % 20;
LUT(hsvFull, lookUpTable, hsvDiscrete);
// get back an BGR image ready to show
Mat dst;
cvtColor(hsvDiscrete, dst, CV_HSV2BGR_FULL);
imshow("Src", src);
imshow("Discrete", dst);
waitKey(0);