30

Pythonでヒートマップを作成しようとしています。このために、可能な値の範囲内のすべての値に RGB 値を割り当てる必要があります。色を青 (最小値) から緑、赤 (最大値) に変更することを考えました。

下の写真の例は、私がどのように色の構成を考えたかを説明しています: 1 (純粋な青) から 3 (純粋な赤) までの範囲があり、2 はその中間であり、緑に似ています。

範囲内の色構成 RGB(1-3)

私は線形補間について読み、(多かれ少なかれ) 最小値と最大値の間の範囲内の特定の値の計算を処理し、RGB タプルを返す関数を作成しました。使用ifelif条件 (これは私を完全に満足させるものではありません):

def convert_to_rgb(minimum, maximum, value):
    minimum, maximum = float(minimum), float(maximum)    
    halfmax = (minimum + maximum) / 2
    if minimum <= value <= halfmax:
        r = 0
        g = int( 255./(halfmax - minimum) * (value - minimum))
        b = int( 255. + -255./(halfmax - minimum)  * (value - minimum))
        return (r,g,b)    
    elif halfmax < value <= maximum:
        r = int( 255./(maximum - halfmax) * (value - halfmax))
        g = int( 255. + -255./(maximum - halfmax)  * (value - halfmax))
        b = 0
        return (r,g,b)

ただし、条件を使用せずに各カラー値の関数を記述できるかどうかは疑問ですif。誰かアイデアがありますか?本当にありがとうございました!

4

4 に答える 4

40
def rgb(minimum, maximum, value):
    minimum, maximum = float(minimum), float(maximum)
    ratio = 2 * (value-minimum) / (maximum - minimum)
    b = int(max(0, 255*(1 - ratio)))
    r = int(max(0, 255*(ratio - 1)))
    g = 255 - b - r
    return r, g, b
于 2013-12-26T23:18:10.010 に答える
20

これを行う別の方法は、可能な限り完全に短くはありませんが、特定の色のセット用にハードコーディングされていないため、より一般的です。これは、任意の色のさまざまなサイズのパレットに対して、指定された範囲の値を線形補間するためにも使用できることを意味します。

また、色は他の色空間で補間された可能性があり、他の色空間よりも満足のいく結果になる可能性があることに注意してください。これは、 Range values to pseudocolorというタイトルの関連する質問に提出した 2 つの個別の回答から得られたさまざまな結果に示されています。

import sys
EPSILON = sys.float_info.epsilon  # Smallest possible difference.

def convert_to_rgb(minval, maxval, val, colors):
    # `colors` is a series of RGB colors delineating a series of
    # adjacent linear color gradients between each pair.

    # Determine where the given value falls proportionality within
    # the range from minval->maxval and scale that fractional value
    # by the total number in the `colors` palette.
    i_f = float(val-minval) / float(maxval-minval) * (len(colors)-1)

    # Determine the lower index of the pair of color indices this
    # value corresponds and its fractional distance between the lower
    # and the upper colors.
    i, f = int(i_f // 1), i_f % 1  # Split into whole & fractional parts.

    # Does it fall exactly on one of the color points?
    if f < EPSILON:
        return colors[i]
    else: # Return a color linearly interpolated in the range between it and 
          # the following one.
        (r1, g1, b1), (r2, g2, b2) = colors[i], colors[i+1]
        return int(r1 + f*(r2-r1)), int(g1 + f*(g2-g1)), int(b1 + f*(b2-b1))

if __name__ == '__main__':
    minval, maxval = 1, 3
    steps = 10
    delta = float(maxval-minval) / steps
    colors = [(0, 0, 255), (0, 255, 0), (255, 0, 0)]  # [BLUE, GREEN, RED]
    print('  Val       R    G    B')
    for i in range(steps+1):
        val = minval + i*delta
        r, g, b = convert_to_rgb(minval, maxval, val, colors)
        print('{:.3f} -> ({:3d}, {:3d}, {:3d})'.format(val, r, g, b))

数値出力:

  Val       R    G    B
1.000 -> (  0,   0, 255)
1.200 -> (  0,  50, 204)
1.400 -> (  0, 101, 153)
1.600 -> (  0, 153, 101)
1.800 -> (  0, 204,  50)
2.000 -> (  0, 255,   0)
2.200 -> ( 51, 203,   0)
2.400 -> (102, 152,   0)
2.600 -> (153, 101,   0)
2.800 -> (203,  51,   0)
3.000 -> (255,   0,   0)

水平グラデーションとして視覚化された出力は次のとおりです。

答えの関数で生成された水平グラデーション

于 2013-12-27T02:16:25.427 に答える
2

if多くの場合、インデックスを使用して を削除して、2 つの値の配列にすることができます。Python には三項条件演算子がありませんが、これは機能します。

r = [red_curve_1, red_curve_2][value>=halfmax]
g = [green_curve_1, green_curve_2][value>=halfmax]
b = [blue_curve_1, blue_curve_2][value>=halfmax]

*_curve_1*_curve_2の式を、それぞれ中点の左または右の定数、勾配、または曲線に 置き換えます。

それらの置換はあなたに任せますが、例えば:

  • red_curve_1そしてblue_curve_2単純に0
  • green_curve_1255*(value-minimum)/(halfmax-minimum)
于 2013-12-26T23:18:12.340 に答える