我需要将图像按照彩虹中的7种颜色(红色,橙色,黄色,绿色,浅蓝色,蓝色,紫色)进行分割。你知道怎么做吗?任何论文或算法都可能。例如,可以通过为每个三元组(r,g,b)分配颜色来完成。但它没有效果,因为我们得到了255 ^ 3的组合。
答案 0 :(得分:4)
HSV colourspace http://en.wikipedia.org/wiki/HSL_and_HSV的“H”组件将为您提供一个合理的数字,表示(连续)彩虹上的位置。
然后很容易将连续空间划分为您选择的七个部分。
答案 1 :(得分:1)
由于您已经拥有所需的7种颜色,因此无需使用群集。一个合理的起点是:对于图像中的每个像素,找到最接近它的7种颜色中的哪一种(使用RGB上的L2距离)并将最接近的颜色分配给该像素。通过首先转换为其他颜色空间(如CIE XYZ),您可能会获得更好(更感性相似)的结果,但这需要进行实验。
答案 2 :(得分:1)
如果颜色是预定义的,那么解决方案就是遍历每个像素并用最近的代表替换。正如carlosdc所说的那样,一些颜色空间转换可以提供比(r1-r2)**2 + (g1-g2)**2 + (b1-b2)**2
更好的结果。
为了加快速度,一个可能的技巧是交换一些内存并缓存给定RGB三元组的结果......即
// Initialize the cache to 255
std::vector<unsigned char> cache(256*256*256, 255);
for (int y=0; y<h; y++)
{
unsigned char *pixel = img + y*w*3 + x;
for int (x=0; x<w; x++, pixel+=3)
{
int r = pixel[0], g = pixel[1], b = pixel[2];
int key = r + (g<<8) + (b<<16);
int converted = cache[key];
if (converted == 255)
{
... find closest representative ...
cache[key] = converted;
}
pixel[0] = red[converted];
pixel[1] = green[converted];
pixel[2] = blue[converted];
}
}
如果颜色数量很少,您可以使用更少的内存。例如,将代表的数量限制为15,每个颜色条目只需要4位(空间的一半),类似下面的内容就可以了吗
std::vector<unsigned char> cache(256*256*256/2, 255);
...
int converted = (key&1) ? (cache[key>>1] >> 4) : (cache[key>>1] & 0x0F);
if (converted == 15) // Empty slot
{
...
cache[key>>1] ^= (key & 1) ? ((converted << 4)^0xF0) : (converted^0x0F);
}
...
如果相反,您知道可能的输入颜色数量很少而且代表的数量会很大,那么标准std::map
可能是一个有效的选择。
答案 3 :(得分:0)
为什么不使用其中一种聚类方法(算法)?例如,k-means算法。否则,谷歌“按颜色分割图像。”
答案 4 :(得分:-1)
如果你希望它看起来不错,你会想要使用抖动,例如:弗洛伊德斯坦伯格犹豫不决:http://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering