2012-11-11 75 views
7

我可能不会使用正确的颜色术语,但我希望基本上能够缩放与所附图片相似的颜色。我一直在寻找饱和度来做到这一点,因为看起来正确的版本只是左侧的饱和版本。如何去色饱和度?

enter image description here

我是想这(我发现),但它是不是找正确可言:

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 

有谁知道一些算法,可以做到这一点的?

+1

搜索这里RGB到HSL,你会发现关于这个专题的许多职位。 – Brad

回答

2

由于@Brad在评论中提到您的帖子,您的第一步是将颜色从RGB转换为HSL or HSV。从那里,降低饱和度是微不足道的 - 只需减去或将饱和度除以某个值即可降低饱和度。

之后,将HSL/HSV颜色转换回RGB并准备好使用。

How to change RGB color to HSV?有一个很好的例子,就像Manipulating colors in .net一样。

2

通过实验发现,减少饱和度不足以获得图片中显示的结果。我在下面显示的代码中使用了OP的问题中的颜色。如果你只是减少饱和度,这里是你会得到什么:

enter image description here

如果您还减少阿尔法/新颜色的不透明性,可以达到更好的效果:

enter image description here

我假设你玩的是参数,你应该能够得到完美的匹配。试着改变alphareducedSaturation2(目前= 40)和GetSaturation分频器(目前为1.3)

这里是我的代码示例:

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 
+1

我也注意到了这一点。我试图解决它的方式是降低饱和度并提高亮度(值)。我能够得到与我的照片非常相似的东西。我会尽力尝试你的,谢谢。 – test

+0

@reedparkes:我尝试玩brigthness--问题在于它变得足够高(= 255),所以你不能再玩了。这是alpha可以提供帮助的地方。实际上,你可以使用全部三个来达到预期的效果。 – Neolisk

9

对于那些想避免一切转换为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); 
+0

像魅力一样工作 – CatalinBerta

+0

这个算法的解释是什么?有没有一个名字?试图学习图像处理atm。 – kosinix

+0

这是使用绿色,红色和蓝色分别对应于图像比例下降的[Luma](https://en.wikipedia.org/wiki/Grayscale#Luma_coding_in_video_systems)的常见假设将r,g,b转换为灰度。所以'L'是灰度图像,然后'f'只是输入RGB图像和灰度图像之间的线性插值。 –

相关问题