Algorithm 颜色分割

Algorithm 颜色分割,algorithm,computer-vision,image-segmentation,Algorithm,Computer Vision,Image Segmentation,我需要将图像分割成7种颜色(红色、橙色、黄色、绿色、浅蓝色、蓝色、紫色),就像彩虹一样。你知道怎么做吗?任何论文或算法都可能被删除。例如,可以通过为每个三元组(r、g、b)指定一种颜色来完成。但是它没有效果,因为我们有255^3个组合。为什么不使用一种聚类方法(算法)?例如,k-均值算法。否则,谷歌“按颜色进行图像分割”。既然您已经拥有了所需的7种颜色,就不需要使用聚类。一个合理的起点是:对于图像中的每个像素,找到7种颜色中最接近它的颜色(使用RGB上的L2距离),并将最接近的颜色指定给该像素。

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

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

既然您已经拥有了所需的7种颜色,就不需要使用聚类。一个合理的起点是:对于图像中的每个像素,找到7种颜色中最接近它的颜色(使用RGB上的L2距离),并将最接近的颜色指定给该像素。通过先转换到其他颜色空间(如CIE XYZ),您可能会获得更好的(在感知上更相似的)结果,但这需要实验。

HSV颜色空间的“H”分量将为您提供一个合理的数字,表示(连续)彩虹上的位置


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

如果颜色是预定义的,那么解决方案就是在每个像素上循环,并用最接近的代表进行替换。如前所述,一些颜色空间变换可能比仅仅
(r1-r2)**2+(g1-g2)**2+(b1-b2)**2更好

为了使事情更快,一个可能的技巧是交换一些内存并缓存给定RGB三元组的结果。。。i、 e

// 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];
    }
}
//将缓存初始化为255
向量缓存(256*256*256255);
对于(int y=0;y1]&0x0F);
if(converted==15)//空插槽
{
...

缓存[key>>1]^=(key&1)((转换如果你想让它看起来好看,你需要使用抖动,例如Floyd Steinberg抖动:

我不理解你的问题-你想把图像减少到7种颜色,将图像中的每种颜色映射到七种颜色中的一种?这通常不称为分割,称为量化。是的,为了简化下一步,首先,我想将图像颜色减少到7,或者可能是+-更多。目的是根据颜色进行一些分组。蓝色有很多种(较暗、较亮一点),作为一个例子,我希望蓝色的所有变化只给出一个值(r=0、g=0、255)对不起,我不明白,你说有抖动或没有抖动是什么意思?解释抖动。这似乎是个好主意,但L2距离足够吗?对不起,你能解释一下L2距离是什么意思吗?模板8颜色设置为(255,0,0)表示红色,(255,0,255)对于粉色来说,这个想法很好,但我有很多不匹配的地方,比如:绿色被检测为黑色。或者白色纸张的照片是由相机拍摄的,带有一些散射,边缘可以检测为浅蓝色等。我试图转换到HSV空间,但如果饱和度或V空间发生变化,颜色可能会变成灰色。如何处理?类似于S和V空间的阈值?我不确定S和V被更改是什么意思,我假设您刚刚有一些输入RGB像素,您想将它们分成七个篮子。没错,无论您使用什么算法,您的一些RGB像素可能是无色的。要处理它们,您需要第八种颜色(灰色),或者你可以根据自己选择的任意规则将它们分配到七种颜色中的一种。最好的选择就是阿德里安所说的。引入八个“灰色”颜色,以及饱和度低于某个阈值的所有像素都被指定为该颜色。请注意,这将包括黑色和白色像素,以及介于两者之间的所有灰色。@maximus:HSV颜色空间的思考方式是一个圆柱体。V表示沿圆柱体的高度,S表示离中心有多远,H表示an角,表示你移动的距离。圆柱体轴线附近的颜色(任意V和H,低S)范围从黑色(低V)到白色(高V),但不管V和H,如果你有低S,颜色的轻微变化可以极大地改变H。这就是为什么你通过阈值S(只有S,而不是V)来切割圆柱体的核心@maximus:你可以使用一些函数从圆柱体上切割出一个更复杂的岩芯,该函数将S与H和V的阈值关联起来。查看以柱坐标表示的形状以获取想法()我需要减少颜色,而不是创建深度。@maximus“创建深度”与“抖动”有什么关系?抖动是一种在减少颜色时传播错误的过程,因此,您可以使用最接近的颜色方法将[浅紫色、浅紫色、浅紫色、浅紫色、浅紫色]映射到[Red、Red、Red、Red、Red、Red],而不是将其映射到[Red、Blue、Red、White、Blue]使用抖动方法查看累积的颜色错误。因此,总体而言,您的图像看起来(如果您斜视)与原始图像的颜色相同。
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);
}
...