11

正しい色の用語を使用していない可能性がありますが、基本的には、添付の画像と同様の色をスケーリングできるようにしたいと考えています。私はこれを行うために彩度を探していました。右のバージョンは左の彩度の低いバージョンであるように見えるからです。

ここに画像の説明を入力してください

私はこれを試していました(私が見つけました)が、それはまったく正しく見えません:

Public Shared Function GetDesaturatedColor(color As Color) As Color
    Const kValue As Double = 0.01R

    Dim greyLevel = (color.R * 0.299R) + _
                    (color.G * 0.587R) + _
                    (color.B * 0.144R)

    Dim r = greyLevel * kValue + (color.R) * (1 - kValue)
    Dim g = greyLevel * kValue + (color.G) * (1 - kValue)
    Dim b = greyLevel * kValue + (color.B) * (1 - kValue)

    ' ColorUtils.ToByte converts the double value 
    ' to a byte safely
    Return color.FromArgb(255, _
                          ColorUtils.ToByte(r), _
                          ColorUtils.ToByte(g), _
                          ColorUtils.ToByte(b))
End Function

誰かがこれを行うことができるいくつかのアルゴリズムを知っていますか?

4

4 に答える 4

17

すべてをHSL/HSVに変換したり、元に戻したりすることを避けたい場合は、これで十分に機能します(「正しい」彩度の低い画像が何であるかによって正しくない場合)。

f = 0.2; // desaturate by 20%
L = 0.3*r + 0.6*g + 0.1*b;
new_r = r + f * (L - r);
new_g = g + f * (L - g);
new_b = b + f * (L - b);

これは、緑、赤、青がそれぞれ画像の減少する比率のルマに対応するという一般的な仮定を使用して、r、g、bをグレースケールに変換しています。したがって、Lはグレースケール画像であり、fは入力RGB画像とそのグレースケール画像の間を線形補間しているだけです。

于 2013-12-28T23:52:27.723 に答える
4

@Bradが投稿へのコメントで述べたように、最初のステップは、色をRGBからHSLまたはHSVに変換することです。そこから、彩度を下げるのは簡単です。彩度を値で減算または除算するだけで、彩度を下げることができます。

その後、HSL / HSVカラーをRGBに変換し直して、使用できるようにします。

RGBカラーをHSVに変更するにはどうすればよいですか?.netでの色の操作と同様に、これを行う方法の良い例があります。

于 2012-11-11T02:32:12.163 に答える
2

実験によると、飽和度を下げるだけでは、写真に示す結果を得るのに十分ではないようです。以下に示すコードで、OPの質問の色を使用しました。飽和度を下げるだけの場合、次のようになります。

ここに画像の説明を入力してください

新しい色のアルファ/不透明度も下げると、より良い結果を得ることができます。

ここに画像の説明を入力してください

パラメータで遊んでいれば、完全に一致するはずだと思います。(現在= 40)と分周器(現在= 1.3)に変更alphaしてみてくださいreducedSaturation2GetSaturation

これが私のコードサンプルです:

Public Function HSVToColor(ByVal H As Double, ByVal S As Double, ByVal V As Double) As Color
  Dim Hi As Integer = (H / 60) Mod 6
  Dim f As Double = H / 60 Mod 1
  Dim p As Integer = V * (1 - S) * 255
  Dim q As Integer = V * (1 - f * S) * 255
  Dim t As Integer = V * (1 - (1 - f) * S) * 255
  Select Case Hi
    Case 0 : Return Color.FromArgb(V * 255, t, p)
    Case 1 : Return Color.FromArgb(q, V * 255, p)
    Case 2 : Return Color.FromArgb(p, V * 255, t)
    Case 3 : Return Color.FromArgb(p, V * 255, q)
    Case 4 : Return Color.FromArgb(t, p, V * 255)
    Case 5 : Return Color.FromArgb(V * 255, q, p)
  End Select
End Function

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
  Dim normalSaturation As Color = Color.FromArgb(255, 216, 53, 45)
  Me.CreateGraphics.FillRectangle(New SolidBrush(normalSaturation), 100, 0, 100, 100)
  Dim reducedSaturation As Color = HSVToColor(normalSaturation.GetHue, normalSaturation.GetSaturation / 1.3, normalSaturation.GetBrightness)
  Dim reducedSaturation2 As Color = Color.FromArgb(40, reducedSaturation)
  Me.CreateGraphics.FillRectangle(New SolidBrush(reducedSaturation2), 0, 0, 100, 100)
End Sub
于 2012-11-11T03:21:19.770 に答える
1

ColorこれがC#で与えられた彩度を変更するための私の公式です。filter: saturate(...)これはW3C仕様で使用される式であるため、結果はCSS効果を適用するのと同じです。

private static Color Saturate(Color c, double saturation) {
   // Values from: https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement , type="saturate"
   var s = saturation;
   Func<double, int> clamp = i => Math.Min(255, Math.Max(0, Convert.ToInt32(i)));
   return Color.FromArgb(255,
      clamp((0.213 + 0.787 * s) * c.R + (0.715 - 0.715 * s) * c.G + (0.072 - 0.072 * s) * c.B),
      clamp((0.213 - 0.213 * s) * c.R + (0.715 + 0.285 * s) * c.G + (0.072 - 0.072 * s) * c.B),
      clamp((0.213 - 0.213 * s) * c.R + (0.715 - 0.715 * s) * c.G + (0.072 + 0.928 * s) * c.B));
}
于 2020-02-11T20:17:13.290 に答える