如何将RGB颜色值映射到色轮上?

时间:2018-07-30 01:35:07

标签: python image-processing colors python-imaging-library

我要调查的色彩数据很少。它采用RGB数据列表的形式。

[(255, 255, 255), (124, 144, 231), ...]

图像使用了受限制的调色板,我想通过沿色轮进行绘制来查看这些颜色是如何“分布”的。另外,我尝试了单个通道的直方图,但这并没有给我我感兴趣的见识。

我搜索并了解到,HSL颜色可以更准确地映射到色轮。但是,转换为HSL后,我仍然感到困惑。颜色仍然由3个数据组成:色相,饱和度和亮度。您如何将3个数据映射到2d平面上?

我在这里了解极坐标:https://www.mathsisfun.com/polar-cartesian-coordinates.html。我尝试通过将HSL数据视为极坐标(色相=角度,饱和度=半径长度(由某些比例缩放))来忽略亮度和绘图。

def polar2cartesian(hsl):
    color_circle_radius = 100
    radius = hsl.saturation * color_circle_radius
    x = radius * math.cos(math.radians(hsl.hue))
    y = radius * math.sin(math.radians(hsl.hue))
    return x, y


...

for hsl in colors: 
    x, y = polar2cartesian(hsl)
    im.point(x, y, hsl.to_rgb())

这不是正确的结果。由于它在多个地方都显示相同的红色色调,例如本例:

bad chart

从RGB转换到色轮上某个位置的正确方法是什么?

1 个答案:

答案 0 :(得分:5)

将3D(H,S,V)颜色映射到2D平面上的问题很难客观地解决,因此我认为我应该对此加以解决,并得出令人愉悦的结果。

我的方法如下:

  1. 对于图像中的每个(R,G,B)像素,请将其转换为(H,S,V)。
  2. 使用H值作为角度并将S值作为幅度,将(H,S,V)颜色转换为2D向量。
  3. 在我们的2D输出图像中找到该矢量的位置,仅在值(V)大于该像素中先前值的情况下才写入像素。 (我的理由是,由于图像可能具有多个颜色足够相似的像素,它们会出现在色轮上的同一位置,因此,由于我们未使用该值进行绘制,因此应给较高值的像素优先显示。 )

现在,在代码中:Entire file

创建一个表以在每个特定位置存储最大值

highest_value = numpy.zeros((image_size, image_size))

将RGB转换为HSV

def rgb_to_point(rgb):
hsv = colorsys.rgb_to_hsv(*rgb)

将其转换为向量

rads = math.tau * hsv[0] - math.pi
mag = hsv[1] * (image_size/2) - 1 

将其转换为图像上的一个点

x = int(math.cos(rads) * mag + (image_size/2))
y = int(math.sin(rads) * mag + (image_size/2))

如果该值较大,则返回该点,否则返回None

if(hsv[2] > highest_value[x][y]):
    highest_value[x][y] = hsv[2]
    return (x, y)

我把所有rgb_to_point函数都调用了,现在我们将它用于图像中的每个像素:

for pixel in img.getdata():
    c = rgb_to_point(pixel)
    if(c):
        imgo.putpixel(c, pixel)

if(c)确定该值是否更高,因为c并非{c}时为None

结果如下:

mountain mountainwheel bird birdywheel

注意:我之所以要处理这样的价值,部分原因是因为我想到的替代方案并不那么好。完全忽略值会导致较暗的像素出现在输出图像上,这通常会导致轮子变丑。将每个输出像素的值都提高到1会导致非常普通的外观,实际上并不能很好地理解原始输入图像。