您可能会考虑使用 K-means,但在这种情况下,它很可能会非常缓慢。更好的方法可能是您自己“手动”执行此操作。假设您有 CV_8UC3 类型的图像,即每个像素由 0 到 255 (Vec3b) 的 3 个 RGB 值表示的图像。您可以将这 256 个值“映射”到仅 4 个特定值,这将产生 4 x 4 x 4 = 64 可能的颜色。
我有一个数据集,我需要确保深色 = 黑色,浅色 = 白色,并减少两者之间所有颜色的数量。这就是我所做的(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 种颜色。