Вы могли бы рассмотреть K-средства, но в этом случае это, скорее всего, будет очень медленно.Лучшим подходом может быть сделать это «вручную» самостоятельно.Допустим, у вас есть изображение типа CV_8UC3
, то есть изображение, где каждый пиксель представлен 3 значениями RGB от 0 до 255 (Vec3b
).Вы можете «сопоставить» эти 256 значений только с 4 конкретными значениями, что даст 4 x 4 x 4
= 64
возможных цветов.
У меня был набор данных, в котором мне нужно было убедиться, что dark = black, свет = белый и уменьшите количество цветов между ними.Вот что я сделал (C ++):
inline uchar reduceVal(const uchar val)
{
if (val < 64) return 0;
if (val < 128) return 64;
return 255;
}
void processColors(Mat& img)
{
uchar* pixelPtr = img.data;
for (int i = 0; i < img.rows; i++)
{
for (int j = 0; j < img.cols; j++)
{
const int pi = i*img.cols*3 + j*3;
pixelPtr[pi + 0] = reduceVal(pixelPtr[pi + 0]); // B
pixelPtr[pi + 1] = reduceVal(pixelPtr[pi + 1]); // G
pixelPtr[pi + 2] = reduceVal(pixelPtr[pi + 2]); // R
}
}
}
, в результате чего [0,64)
становится 0
, [64,128)
-> 64
и [128,255)
-> 255
, давая 27
цвета:
Мне кажется, это аккуратно, совершенно ясно и быстрее, чем что-либо еще упомянутое в других ответах.
Вы могли бы также рассмотретьуменьшив эти значения до одного из кратных некоторого числа, скажем:
inline uchar reduceVal(const uchar val)
{
if (val < 192) return uchar(val / 64.0 + 0.5) * 64;
return 255;
}
, что даст набор из 5 возможных значений: {0, 64, 128, 192, 255}
, то есть 125 цветов.