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

0 python colors image-processing python-imaging-library

我有少量要查询的颜色数据。它采用RGB数据列表的形式。

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

该图像使用受限的调色板,我想通过沿色轮进行绘制来查看这些颜色是如何“分布”的。作为替代方案,我尝试了各个通道的直方图,但这并没有给我带来我感兴趣的见解。

我在Google上搜索并了解到,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())
Run Code Online (Sandbox Code Playgroud)

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

不良图表

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

Ali*_*den 5

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

我的方法如下:

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

现在,在代码:整个文件

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

highest_value = numpy.zeros((image_size, image_size))
Run Code Online (Sandbox Code Playgroud)

将RGB转换为HSV

def rgb_to_point(rgb):
hsv = colorsys.rgb_to_hsv(*rgb)
Run Code Online (Sandbox Code Playgroud)

将其转换为向量

rads = math.tau * hsv[0] - math.pi
mag = hsv[1] * (image_size/2) - 1 
Run Code Online (Sandbox Code Playgroud)

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

x = int(math.cos(rads) * mag + (image_size/2))
y = int(math.sin(rads) * mag + (image_size/2))
Run Code Online (Sandbox Code Playgroud)

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

if(hsv[2] > highest_value[x][y]):
    highest_value[x][y] = hsv[2]
    return (x, y)
Run Code Online (Sandbox Code Playgroud)

我调用了所有这些rgb_to_point函数,现在我们将其用于图像中的每个像素:

for pixel in img.getdata():
    c = rgb_to_point(pixel)
    if(c):
        imgo.putpixel(c, pixel)
Run Code Online (Sandbox Code Playgroud)

if(c)确定该值是否更高,因为c并非None在那时。

结果如下:

山 山轮 鸟 飞轮

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