【问题标题】:Sorting a list of RGB triplets into a spectrum将 RGB 三元组列表排序为频谱
【发布时间】:2011-09-06 17:30:06
【问题描述】:

我有一个 RGB 三元组列表,我想将它们绘制成类似光谱的图。

我已将它们转换为人们似乎推荐的 HSV。

from PIL import Image, ImageDraw
import colorsys

def make_rainbow_rgb(colors, width, height):
    """colors is an array of RGB tuples, with values between 0 and 255"""

    img = Image.new("RGBA", (width, height))
    canvas = ImageDraw.Draw(img)

    def hsl(x):
        to_float = lambda x : x / 255.0
        (r, g, b) = map(to_float, x)
        h, s, l = colorsys.rgb_to_hsv(r,g,b)
        h = h if 0 < h else 1 # 0 -> 1
        return h, s, l

    rainbow = sorted(colors, key=hsl)

    dx = width / float(len(colors)) 
    x = 0
    y = height / 2.0
    for rgb in rainbow:
        canvas.line((x, y, x + dx, y), width=height, fill=rgb)
        x += dx
    img.show()

但是,结果看起来不太像一个漂亮的彩虹-y 光谱。我怀疑我需要转换为不同的色彩空间或以不同的方式处理 HSL 三元组。

有谁知道我需要做什么才能使这些数据看起来大致像彩虹?

更新:

我在玩希尔伯特曲线并重新审视了这个问题。将 RGB 值(两幅图像中的颜色相同)按希尔伯特曲线上的位置排序会产生一个有趣的(如果仍然不完全令人满意)的结果:

【问题讨论】:

  • 请阅读此内容,然后重新考虑您正在做的事情:brucelindbloom.com/index.html?Equations.html。光谱是一个单一的波长值,而不是 HSL 三倍或类似的东西。这个等式并不简单,所有 RGB 颜色在光谱中都没有位置。此外,这可能会有所帮助:pfk.ff.vu.lt/cie/1931CIE_explanation.htm。你真的需要重新考虑你在做什么。
  • @S.Lott -- 是的,我知道从技术上讲,这是一个傻瓜的差事。我真的不需要任何与物理光相关的东西,只需要表现出最大程度令人愉​​悦的渐变(即最小化感知不连续性)。
  • 更新——我决定在两个轴上绘制颜色,色调和饱和度,让亮度自然变化。结果看起来不错(但占用更多空间)
  • 如果您正在寻找real spectral colors,请特别注意 R、G、B 图表,并尝试以类似的方式对颜色进行排序。然后按强度重新排列“相同”的颜色,这样你就不会有太多的颠簸......

标签: python python-imaging-library color-space spectrum hsv


【解决方案1】:

您正在尝试将三维空间转换为一维空间。正如 Oli 所说,不能保证你能从中创造出令人愉悦的彩虹。

您可以做的是根据饱和度和值/亮度将颜色“分桶”到几个不同的类别中,然后在类别中进行排序,以获得几个独立的渐变。例如,经典彩虹首先是高饱和度颜色,然后是中饱和度高价值颜色(粉彩),然后是低饱和度(灰色)。

或者,如果您只关心彩虹,则转换为 hsl,然后将饱和度调整为 1.0 并将值调整为 0.5,然后转换回 rgb 并渲染它而不是原始颜色。

【讨论】:

  • 我喜欢分开彩虹的想法。我会玩那个。谢谢
  • 正如rephorm所说的答案,你可以使用Hibert曲线来减少3D到2D空间。
【解决方案2】:

大概你是按色调排序的(即H)?如果 SL (或 V) 是恒定的,那将给出一个很好的结果,但如果它们独立变化,那么你会得到一个有点乱!

【讨论】:

  • 是的,我按 h、s、l 排序,最后 2 个的可变性导致一团糟。我想知道是否有一些 h、s 和 l 的功能可以使某些东西变得漂亮。
  • @Jason:一般来说,没有。正如@Russell 在他的回答中所说,您正在尝试将 3D 空间折叠成 1D 线。除非您实际修改输入颜色,否则您将无法避免不连续性。
【解决方案3】:

一种减少色彩空间维度的有趣方法是使用空间填充Hilbert curve。两篇相关文章是:

他们都考虑 3d -> 2d 缩减,但映射到 1d 曲线的中间步骤可能是您的问题的解决方案。

【讨论】:

【解决方案4】:

这是我最近做的一些彩虹,你可以修改想法做你想做的事

from PIL import Image, ImageDraw  # pip install pillow
import numpy as np
from matplotlib import pyplot as plt

strip_h, strip_w = 100, 720
strip = 255*np.ones((strip_h,strip_w,3), dtype='uint8')
image_val = Image.fromarray(strip)
image_sat = Image.fromarray(strip)
draw0 = ImageDraw.Draw(image_val)
draw1 = ImageDraw.Draw(image_sat)
for y in range(strip_h):
    for x in range(strip_w):
        draw0.point([x, y], fill='hsl(%d,%d%%,%d%%)'%(x%360,y,50))
        draw1.point([x, y], fill='hsl(%d,%d%%,%d%%)'%(x%360,100,y))

plt.subplot(2,1,1)
plt.imshow(image_val)
plt.subplot(2,1,2)
plt.imshow(image_sat)
plt.show()

【讨论】:

  • 这段代码用一系列漂亮的颜色填充空间。我的问题是我有一个我想要彩虹化的颜色列表。有点相反的问题。不过,感谢您的代码。
【解决方案5】:

这似乎不正确。

canvas.line((x, y, x + dx, y), width=height, fill=rgb)

试试这个。

canvas.rectangle([(x, y), (x+dx, y+height)], fill=rgb)

【讨论】:

  • 它们都产生相同的东西,尽管我承认使用 'rectangle' 绘制矩形比绘制粗线更有意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-04
  • 1970-01-01
相关资源
最近更新 更多