40

問題: JavaScript で 2 つの色を混ぜて、結果の色を取得したい。SOには同様の質問がたくさんありますが、実際に正しく機能するものは見つかりません。2 つの異なる色の塗料 (顔料) とライトを混合すると、非常に異なる結果が得られることはわかっています ( http://en.wikipedia.org/wiki/Color_mixing )。

以下は、私がすでに見て実装しようとした質問と提案された解決策です。

1: 2 つの RGB カラー ベクトルを混合して結果を得る ということ
で、RGB で色を混合します。私はそれを実装しましたが、場合によっては機能する場合と機能しない場合があります。

作業例: ->redとの混合。すごい!http://jsbin.com/afomim/1/edityelloworange

動作しない例: ->blueとの混合。それほど素晴らしいことではありません!:) http://jsbin.com/afomim/5/edit RGB では と混合しても決して.yellowgray
blueyellowgreen

ここでは答えは見つかりません。先に進みましょう。

2: 絵の具のように色(色)を足し合わせる(青+黄=緑など)

このディスカッションで提案されているように、CMYK 値を使用してみましょう。と混合cyanすると: http://jsbin.com/igaveg/1/edityellow得られますが、 と混合すると. http://jsbin.com/igaveg/2/edit -> 動かない!green

blueyellowblack

3: C# で「自然に」色を混ぜるには?
非常によく似た質問です。最も支持された回答は、色を LAB に変換することを提案しており、この解決策は有望に思えます。
だから私は自分の色をLABに変換しました。変換アルゴは正しいです、私はそれをテストしました!

http://jsbin.com/oxefox/1/edit

これで LAB に 2 つの色ができましたが、それらをどのように混ぜ合わせますか?

blue: と混合しyellowて完全な を与えるアルゴリズムがおそらく見つからないことはわかっていますが、greengreen に似たものを生成できることを願っています :)

4

12 に答える 12

46

私はこの質問に 3 ~ 4 日を費やしました。これは本当に複雑な問題です。

2 つの色を「自然に」混ぜたい場合は、次のようにします。

  1. CMYK ミキシング: これは完璧な解決策ではありませんが、今すぐ解決策が必要で、主題についての学習、実験、およびコーディングに何ヶ月も費やしたくない場合は、こちらを確認してください: https://github.com/ AndreasSoiron/Color_mixer

  2. クベルカムンク理論の実装。私はそれについて読んで、それを理解しようと多くの時間を費やしました. これは、プロフェッショナルなソリューションが必要な場合に適した方法ですが、混合する色ごとに 6 つのパラメーター (反射率、吸収率など) が必要です。R、G、Bがあるだけでは十分ではありません。理論を実装することは難しくありませんが、各色について必要なパラメーターを取得することは、欠けている部分のようです. あなたがそれを行う方法を理解したら、私に知らせてください:)

  3. 実験的: iPad アプリの開発者であるPaperが行ったことを実行できます。彼らは手作業で 100 組の人気のある色を選択し、どのようにブレンドするかを目でテストしました。詳細については、こちらをご覧ください。

私は個人的に CMYK ミキシングを今のところ実装します。時間があれば、Fiftythree のようなものを作ろうと思います。表示されます:)

于 2013-03-06T10:36:10.187 に答える
12

RYB カラー モデルは、混色の計算に適した選択肢となる可能性があります。ウィキペディアによると、主にアートとデザインの教育、特に絵画で使用されています。

2 色を混合するには、両方の色を RGB から RYB に変換し、各色成分を追加して色を混合し、結果の色を RYB から RGB に変換します。

Online Color Mixing Toolを使用してこれを試してみましたが、結果は次のとおりです。

  • 0000FF (青) と #FFFF00 () を混ぜると#008000 (濃い緑) になります。

  • FF0000 () と #FFFF00 () を混ぜると #FFA000 (オレンジ) になります。

したがって、この方法では、期待どおりの結果が得られます。

残念ながら、RGB から RYB に変換してから RGB に戻すための「すぐに使用できる」数式のリファレンスを見つけることができませんでした。

ペーパー Paint Inspired Color Mixing and Compositing for Visualization - Gossett と Chen は、「2 ACHIEVING INTUITIVE COLOR MIXING」セクションで RYB カラー モデルの一般的な考え方を説明しています。

その論文によると、RYB から RGB への変換は Trilinear 補間によって行われます。

難しい部分は、RGB から RYB への変換です。これは、トリリニア補間の反転が必要になるためです。詳細については、RGB と RYB の色空間間の変換を参照 してください。

この回答が計算の完全な式を提供していない場合でも、続行する方法についていくつかのアイデアが得られることを願っています.

于 2013-02-12T20:07:39.583 に答える
3

このプロジェクトは本当に役に立ちました: https://github.com/ProfJski/ArtColors

そのコードを Objective-C に変換し、説明どおりに動作することを確認しました。

以下に引用されている「原則 5」のセクションを参照してください。

ArtColors は、次のように、2 つの RGB 入力と混合比率のみを使用して、最小限のコードで現実的な方法で 2 つの色を減算的に混合する単純な関数呼び出しを提供する必要があります。

Return Color=SubtractiveMix(Color a, Color b, percentage)

ArtColors は、(私が思うに) 他の方法のコードのほんの一部でかなり良い結果をもたらすアルゴリズムを使用し、反射率データや複雑な計算式を計算または保存する必要はありません。目標は、コードの 20% のみで 80% のリアリズムを実現することです。

基本的なアプローチは、塗料が実際にどのように混ざるかを考えることから着想を得ました。絵の具の混合のクローズアップを調べます。

塗料混合

注意深く見ると、一部の領域で 2 つの絵の具が完全に混ざり合っており、その結果が減法であることがわかります。黄色と青が、はるかに濃い緑を作っています。赤と青がとても濃い紫を作っています。しかし、ブレンドがそれほど完全ではない他の領域では、黄色と青の細い線が並んで存在します. これらの塗料は黄色と青色の光を反射しています。離れたところから見ると、はっきりとした渦巻きが小さすぎて見えない場合 、これらの色は目によって加算的にブレンドされます。

さらに、塗料の混合は化学的な意味での混合であると考えてください。化学変化は起こりません。赤と青の分子はまだ完全なブレンドの中にあり、分離していたときとまったく同じように、赤と青の光を反射します。光が媒質内で跳ね返るため、多くの地下物理的効果が起こっています。入射光はある分子に吸収されて反射され、次に別の分子に反射され、最終的にその結果が目に反射します。

これはどのように私たちの問題を解決するのに役立ちますか?

厳密な減算アプローチは、白から開始し、次に白からカラー A とカラー B の RGB 値を減算し、残ったものを返します。 多くの場合、このアプローチは暗すぎます。 なんで?各顔料の一部は、まだ小さなスケールでその独特の色を反映しています. 部分的に加算的で部分的に減算的なアプローチを取ると、より現実的な結果が得られます!

さらに、色 A = 色 B の場合、関数は同じ色を返す必要があります。同じ色と同じ色を混ぜると、同じ色になるはずです!厳密な減算アルゴリズムを使用すると、結果は元の色相のより暗いバージョンになります (入力カラー値が White から2 回減算されるため)。2 つの入力カラーが近いほど、ブレンドで見られる変化は少なくなります。

減法混色の ArtColor コードは次のとおりです。

Color ColorMixSub(Color a, Color b, float blend) {
    Color out;
    Color c,d,f;

    c=ColorInv(a);
    d=ColorInv(b);

    f.r=max(0,255-c.r-d.r);
    f.g=max(0,255-c.g-d.g);
    f.b=max(0,255-c.b-d.b);

    float cd=ColorDistance(a,b);
    cd=4.0*blend*(1.0-blend)*cd;
    out=ColorMixLin(ColorMixLin(a,b,blend),f,cd);

    out.a=255;
return out;
}

コードの説明: Color aColor bは入力色です。 blend線形補間 (LERP) のように、ブレンドする各色の量を 0 から 1.0 で指定します。0.0 = すべてのカラー A、1.0 = すべてのカラー B。0.5 = A と B の 50%-50% の混合。

まず、色 a と b の RGB 反転を見つけ、それらを新しい色 c と d に割り当てます。

    c=ColorInv(a);
    d=ColorInv(b);

次に、純粋な RGB ホワイトから c と d の両方を減算し、結果をゼロにクランプして、結果を色 f に割り当てます。

    f.r=max(0,255-c.r-d.r);
    f.g=max(0,255-c.g-d.g);
    f.b=max(0,255-c.b-d.b);

これまでのところ、f は純粋に減算的な結果であり、上記の問題に悩まされています。

次に、色 a と色 b の間の「色距離」を計算します。これは、RGB 空間でのそれらの間のベクトル距離であり、0.0 (同じ色) と 1.0 (白と黒のように完全に反対) の間で正規化されています。

float cd=ColorDistance(a,b);

この値は、2 つの類似した色相を混合しても結果があまり変わらないという問題を解決するのに役立ちます。次に、色距離係数cdは、二次伝達関数によって変換されます。これにより、減法混合と加法混合の量が調整されます。

cd=4.0*blend*(1.0-blend)*cd;

アートカラーブレンド

エンドポイントにより、0% または 100% に近いブレンド パーセンテージが元の入力色に非常に近くなります。二次曲線は、次に来るミックスに適した色域を提供します。曲線のピークは、色の距離によって決まります。この関数の出力は、結果における加法的ブレンディングと減法的ブレンディングの量を決定します。より離れた色は、より減法的なダイナミクス (y=1.0 で完全に減法化) とブレンドされます。同様の色は、減法要素を持つより加法的なダイナミクス (より平坦な曲線) とブレンドされます。二次伝達関数の最大値は正規化された色距離であるため、色空間で正反対の色が完全に減算的にブレンドされます。

最後の行はすべての作業を行います:

out=ColorMixLin(ColorMixLin(a,b,blend),f,cd);`

まず、指定された比率で色 A と色 Bを加算的に混合します。これは によって達成されます。これは、上の画像の色の細かい渦巻きと表面下の相互作用の加算ブレンド効果を表しています。この要因がない場合、厳密に減法的なアプローチでは奇妙な結果が生じる可能性があります。この加算結果は、との間の色距離に基づく上記の伝達関数に従って、純粋な減算結果 とブレンドされます。blendColorMixLin(a,b,blend)color fColor aColor b

出来上がり!広範囲の入力色でかなり良い結果が得られます。

于 2021-05-09T15:13:27.410 に答える
1

これは、CIE-LCh 色空間での混色について私が書いた良い記事です。この記事では、色相、彩度、および輝度を、目の知覚と一致する方法で保持する混合を生成します。

カラーブレンディングの改善

于 2014-02-28T22:43:44.207 に答える
1

これを使用してRGBをCMYKに変換してから:

// CMYK colors
colorA = [2, 90, 94, 0];
colorB = [4, 0, 80, 0]; 

colorMixC = (colorA[0] + colorB[0]) / 2;
colorMixM = (colorA[1] + colorB[1]) / 2;
colorMixY = (colorA[2] + colorB[2]) / 2;
colorMixK = (colorA[3] + colorB[3]) / 2;

最後に、これを使用してCMYKをRGBに変換します

于 2015-07-30T09:30:41.460 に答える
0

CMYまたはRGBカラー モデルを使用する必要があります。

なぜBlue+YellowはできないのGrayですか?

Blue+ Yellow= ( Cyan+ Magenta) + Yellow=> Gray. なぜだめですか?

これを見てください。

したがって、RGB (CMY) を使用して色を混ぜることができます。

于 2013-10-10T08:55:02.413 に答える