3

いくつかの RGB LED を制御して、赤から紫にフェードしようとしています。HSV から RGB への変換を使用して、色相 0 から色相 300 までスイープできるようにしています (それを超えると赤に戻ります)。私が気付いた問題は、スペクトルのシアンとブルーのセクションでかなりの時間を費やしているように見えることです. そこで、HSVスペクトルがどのように見えるかを調べたところ、これが見つかりましたL

ここに画像の説明を入力

スペクトルの半分以上が緑と青の間で費やされていることに気づきませんでした。

しかし、私はそれがもっとこのように見えることを本当に望んでいます:

ここに画像の説明を入力

その「標準的な」虹色の素敵なブレンドで。これは、通常の色相値のある種の S カーブになると思いますが、そのカーブを計算する方法がよくわかりません。

これを内部で処理する実際の HSV から RGB へのアルゴリズムは素晴らしいでしょう (実際には Arduino 用のコードですが)、その色相曲線を計算する方法の説明だけでも大歓迎です。

4

2 に答える 2

3

FastLED はこれのバージョンを実行します: https://github.com/FastLED/FastLED/wiki/FastLED-HSV-Colors

高速 LED HSV

HSLUV は別のオプションです: http://www.hsluv.org/。さまざまな言語のライブラリがあります。

HSLUV

また、これは興味深いテクニックです: https://www.shadertoy.com/view/4l2cDm

const float tau = acos(-1.)*2.;

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord.xy / iResolution.xy;

    vec3 rainbow = sqrt( //gamma
        sin( (uv.x+vec3(0,2,1)/3.)*tau ) * .5 + .5
    );

    fragColor.rgb = rainbow;
}

ここに画像の説明を入力

詳細については、https : //en.wikipedia.org/wiki/Rainbow#Number_of_colours_in_spectrum_or_rainbowも参照してください。

于 2018-07-30T02:59:09.420 に答える
3

http://www.fourmilab.ch/documents/specrend/には、波長を CIE コンポーネント (目の 3 種類の錐体センサーの出力にほぼ対応する) に変換する方法と、その方法がかなり詳細に説明されています。それらをRGB値に変換します(一部の波長には、典型的なRGB色域に対応するRGBないという警告があります)。

または: CIE L*a*b* のようなさまざまな「知覚的に均一な色空間」があります (例: http://en.wikipedia.org/wiki/Lab_color_spaceを参照)。それらのいずれかを選択し、そのスペースで開始色と終了色を結ぶ直線に沿って同じ手順を実行し、RGB に変換できます。

ただし、どちらもアプリケーションにとってはやり過ぎである可能性が高く、単純で純粋に経験的なものよりもはるかに (または少しでも) 優れている明確な理由はありません。では、次のことを行ってみませんか。

  1. 開始色と終了色を選択します。簡単にするために、HSV 空間に S=1 と V=1 があるとします。それらを書き留めます。
  2. 投稿した色相の「スペクトル」に沿って見て、開始点と終了点のほぼ中間に見える色を見つけます。これをメモしてください。
  3. ここで再び二等分します。開始点と中間点の中間、および中間点と終了点の中間にある色を見つけます。
  4. 色相スケールを 8 または 16 の「知覚的に等しい」部分に分割するように、さらに 1 ~ 2 回繰り返します。
  5. RGB に変換し、それらをルックアップ テーブルに貼り付け、その間を線形補間します。
  6. 見栄えが良くなるまで、RGB 値を少し調整します。

これは完全にアドホックであり、原則はまったくありませんが、おそらくかなりうまく機能し、最終的なコードは基本的に簡単になります。

void compute_rgb(int * rp, int * gp, int * bp, int t) {
  // t in the range 0..255 (for convenience)
  int segment = t>>5; // 0..7
  int delta = t&31;
  int a=rgb_table[segment].r, b=rgb_table[segment+1].r;
  *rp = a + ((delta*(b-a))>>5);
  a=rgb_table[segment].g; b=rgb_table[segment+1].g;
  *gp = a + ((delta*(b-a))>>5);
  a=rgb_table[segment].b; b=rgb_table[segment+1].b;
  *bp = a + ((delta*(b-a))>>5);
}

(使用可能なすべてのサイクルを保存することを気にしない場合は、コードをいくらか明確にすることができます)。

価値のあることとして、私の目は、約 (0)、40、60、90、150、180、240、270、(300) の色相値に分割点を配置しました。あなたのマイレージは異なる場合があります。

于 2011-03-02T02:09:46.937 に答える