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);
have a look also in this thread, it might be useful. The use of a lookup table as @pklab proposed might be useful as well.