18

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()

ただし、結果は、きれいな虹色のスペクトルとはあまり似ていません。別の色空間に変換するか、HSL トリプレットを別の方法で処理する必要があると思います。

これはスペクトルのようには見えません

このデータを大まかに虹のように見せるために何をする必要があるか知っている人はいますか?

アップデート:

私はヒルベルト曲線をいじっていて、この問題を再検討しました。ヒルベルト曲線に沿った位置で RGB 値 (両方の画像で同じ色) を並べ替えると、興味深い (それでも完全に満足できるものではない場合) 結果が得られます。

ヒルベルト曲線に沿って並べ替えられた RGB 値。

4

5 に答える 5

12

3 次元空間を 1 次元空間に変換しようとしています。オリが言うように、あなたがそれから楽しい虹を作れるという保証はありません.

できることは、彩度と値/明度に基づいて色をいくつかの異なるカテゴリに「バケット」し、カテゴリ内で並べ替えて、いくつかの独立したグラデーションを取得することです。たとえば、最初にクラシック レインボーの高彩度カラー、次に中彩度の高値カラー (パステル)、低彩度 (グレー) の順に配置します。

または、気にするのが虹だけの場合は、hsl に変換してから、彩度を 1.0 に、値を 0.5 にスラムし、rgb に戻して元の色の代わりにレンダリングします。

于 2011-06-01T23:59:35.907 に答える
6

おそらく、色相(つまりH)でソートしていますか?SL (またはV ) が一定の場合は良い結果が得られますが、それらが独立して変化する場合は、少し混乱します。

于 2011-06-01T23:50:14.783 に答える
4

色空間の次元を削減する興味深い方法は、空間充填ヒルベルト曲線を使用します。関連する 2 つの記事は次のとおりです。

どちらも 3d -> 2d 削減を考慮していますが、1d 曲線へのマッピングの中間ステップが問題の解決策になる可能性があります。

于 2012-04-07T07:09:36.823 に答える
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()

ここに画像の説明を入力

于 2011-06-02T04:43:37.473 に答える
1

これは正しくないようです。

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

これを試して。

canvas.rectangle([(x, y), (x+dx, y+height)], fill=rgb)
于 2011-06-02T10:05:42.557 に答える