4

我需要像彩虹一样用 7 种颜色(红色、橙色、黄色、绿色、浅蓝色、蓝色、紫色)分割图像。你知道怎么做吗?任何论文或算法都可能是。例如,可以通过为每个三元组 (r, g, b) 分配颜色来完成。但它并不有效,因为我们得到了 255^3 的组合。

4

5 回答 5

4

HSV 颜色空间http://en.wikipedia.org/wiki/HSL_and_HSV的“H”组件将为您提供一个合理的数字,代表(连续)彩虹上的位置。

然后很容易将连续空间划分为您选择的七个部分。

于 2011-07-29T05:31:38.627 回答
1

由于您已经拥有所需的 7 种颜色,因此无需使用聚类。一个明智的起点是:对于图像中的每个像素,找出最接近它的 7 种颜色(使用 RGB 上的 L2 距离)并将最接近的颜色分配给该像素。通过首先转换为其他颜色空间(如 CIE XYZ),您可能可以获得更好(在感知上更相似)的结果,但这需要进行实验。

于 2011-07-29T05:11:58.180 回答
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可能是一个有效的替代方案。

于 2011-07-29T05:57:53.217 回答
0

为什么不使用其中一种聚类方法(算法)?例如,k-means 算法。否则,谷歌“按颜色分割图像”。

于 2011-07-29T05:01:55.210 回答
-1

如果你想让它看起来不错,你会想要使用抖动,例如 Floyd Steinberg 抖动: http ://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering

于 2011-07-29T08:04:51.600 回答