我想将像素的颜色淡化为白色,但显然保持相同的颜色。如果我有一个像素(200,120,40)
,将为每个值添加10以使(210,130,50)
使其颜色相同,只是更轻,还是会完全改变颜色?例如,我知道转到(100,100,100)
的{{1}}是灰度渐变。我希望RGB值相同,我想按数字进行,如图所示。是否有这样的等式?
答案 0 :(得分:15)
有很多方法可以做到这一点。您如何选择这取决于您是否重视速度和简单性或感知均匀性。如果你需要它是真正统一的,你需要用颜色配置文件定义RGB颜色,你需要配置文件的原色,这样你就可以转换为XYZ,然后转换到LAB,你可以操作L通道。
大多数情况下,您不需要这样做,而是可以使用像Photoshop一样的简单HSB模型。
要做到这一点,您只需想象一下RGB点与3D空间中的白点之间的一条线,并沿着该线移动颜色。实际上,您可以为该行创建参数方程并移动参数。
import numpy as np
def lighter(color, percent):
'''assumes color is rgb between (0, 0, 0) and (255, 255, 255)'''
color = np.array(color)
white = np.array([255, 255, 255])
vector = white-color
return color + vector * percent
0.0的百分比将返回相同的颜色,1.0将返回白色。之间的一切都将是相同色调的浅色调。这应该给你的结果与Photoshop的HSB实现一致,但将取决于设备,可能不完全统一。
如果你有RGB [200, 100, 50]
并输入.50的百分比,那么它应该返回RGB[ 227.5 177.5 152.5]
Photoshop报告的色调为20º。
没有numpy这样做并不难,但元素操作很方便。
根据评论进行修改:
我不是建议你这样做,除非你知道你真的需要这么做。但是如果你想转换为LAB,你可以毫不费力地进行操作。最重要的是你需要知道你的RGB数字开头的颜色空间,或者你需要对它们的含义做一些假设。由于sRGB在网络上非常标准,我会在这里假设。
转换并不困难,但很容易出错。令人高兴的是,有一个非常好的colormath模块和良好的文档:https://github.com/gtaylor/python-colormath
使用它可以在sRGB和LAB之间进行转换,如下所示:
from colormath.color_objects import sRGBColor, LabColor
from colormath.color_conversions import convert_color
sRGB = sRGBColor(126, 126, 126, is_upscaled=True) # or between [0, 1] with out is_upscaled
lab = convert_color(sRGB, LabColor)
实验室现在是一种带有亮度通道lab.lab_l
的颜色,您可以在黑色(0)和白色(100)之间上下移动。这应该比HSB在感知上更统一(但是,根据您的应用,可能还不足以保证工作)。
您只需更改lab_l
然后转换回来:
lab.lab_l = 80
new_sRGB = convert_color(lab, color_objects.sRGBColor).get_upscaled_value_tuple()
new_sRGB
现在是[198, 198, 198]
。 colormath为您处理光源和伽玛问题。
答案 1 :(得分:5)
只需在颜色和白色之间进行线性插值:
def lerp(a, b, t):
return a*(1 - t) + b*t
import numpy as np
white = np.array([255, 255, 255])
my_color = np.array([...])
lightened25 = lerp(my_color, white, 0.25)
或者没有numpy:
lightened25 = [lerp(c, w, 0.25) for c, w in zip(my_color, white)]
答案 2 :(得分:4)
我更喜欢使用HSV color mode。
要使颜色变灰,您必须降低饱和度因子。
标准colorsys模块可以帮助RGB< - > HSV转换,但请注意:colorsys
使用范围[0,1)中的通道值进行操作,而不是[0,256]。
有完整的代码示例:
>>> from colorsys import hsv_to_rgb, rgb_to_hsv
>>> color = (200, 120, 40)
>>> normalized_color = (color[0]/256., color[1]/256., color[2]/256.)
>>> normalized_color
(0.78125, 0.46875, 0.15625)
>>> hsv_color = rgb_to_hsv(*normalized_color)
>>> hsv_color
(0.08333333333333333, 0.8, 0.78125)
>>> grayed_hsv_color = (hsv_color[0], 0.6, hsv_color[2])
>>> grayed_rgb_color = hsv_to_rgb(*grayed_hsv_color)
>>> grayed_rgb_color
(0.78125, 0.546875, 0.3125)
>>> denormalized_rgb_color = (int(grayed_rgb_color[0]*256), int(grayed_rgb_color[1]*256), int(grayed_rgb_color[2]*256))
>>> denormalized_rgb_color
(200, 140, 80)
答案 3 :(得分:2)
它并不那么简单,因为在您的显示器中,每个颜色通道的权重都不同。我说最好的选择是在scikit图像中通过转换为灰色,调暗或增亮,然后反向转换为颜色来执行此操作。 Scikit-image将保持颜色笔直。
from skimage.color import gray2rgb, rgb2gray
scale_factor = 0.9 #90 percent
img_new = gray2rgb(rgb2gray(img) * scale_factor)
如果您想直接使用色调,饱和度和值,请查看以下示例:
http://scikit-image.org/docs/dev/auto_examples/plot_tinting_grayscale_images.html
答案 4 :(得分:2)
正如MarkM所说,HSB(或HSL)是一种简单的方法,但不会给出完美的色调常数。如果这足够好(我假设您需要自己的方法而不是模块),那么this page就会有代码来执行此操作。
在python中它看起来像这样:
def rgb_to_hsl(rgb):
'''
Converts an rgb (0..255) tuple to hsl
'''
r, g, b = rgb
_r = r / 255 # RGB in percentage
_g = g / 255
_b = b / 255
rgbMin = min(_r, _g, _b)
rgbMax = max(_r, _g, _b)
rgbDelta = rgbMax - rgbMin
l = ( rgbMax + rgbMin ) / 2
if rgbDelta == 0: #Greyscale
h = 0
s = 0
else: # Chromatic data...
if l < 0.5: s = rgbDelta / (rgbMax + rgbMin)
else: s = rgbDelta / (2 - rgbMax - rgbMin)
deltaR = (((rgbMax - _r) / 6) + rgbDelta/2) / rgbDelta
deltaG = (((rgbMax - _g) / 6) + rgbDelta/2) / rgbDelta
deltaB = (((rgbMax - _b) / 6) + rgbDelta/2) / rgbDelta
if _r == rgbMax: h = deltaB - deltaG
elif _g == rgbMax: h = 1/3 + deltaR - deltaB
elif _b == rgbMax: h = 2/3 + deltaG - deltaR
if h < 0: h += 1
if h > 1: h -= 1
return (h, s, l)
def hsl_to_rgb(hsl):
'''
Converts a hsl tuple to rgb(0..255)
'''
h, s, l = hsl
if s == 0: #Greyscale
r = l * 255
g = l * 255
b = l * 255
else:
if l < 0.5: var_2 = l * (1 + s)
else: var_2 = l + s - (s * l)
var_1 = 2 * l - var_2
r = 255 * hue_to_RGB(var_1, var_2, h + 1/3)
g = 255 * hue_to_RGB(var_1, var_2, h)
b = 255 * hue_to_RGB(var_1, var_2, h - 1/3)
return r, g, b
def hue_to_RGB (v1, v2, vH):
'''
Helper for hsl_to_rgb
'''
if vH < 0: vH += 1
if vH > 1: vH -= 1
if (6 * vH) < 1: return v1 + (v2 - v1) * 6 * vH
if (2 * vH) < 1: return v2
if (3 * vH) < 2: return v1 + (v2 - v1) * 6 * (2/3 - vH)
return v1
然后变亮:
def lighten(rgb):
'''
Given RGB values, returns the RGB values of the same colour slightly
brightened (towards white)
'''
h,s, l = rgb_to_hsl(rgb)
l = min(l+0.1, 1) #limit to 1
return hsl_to_rgb((h, s, l))
此方法的好处是增量是总亮度的百分比。修改此项以将百分比作为输入将是微不足道的。
您可以使用此代码对数学方程进行反向工程,或参阅HSL to RGB。
答案 5 :(得分:1)
您可能需要this answer查看denis:
RGB - &gt; ^ gamma - &gt; Y - &gt; L *
在色彩科学中,常见的RGB值,如html rgb(10%,20%,30%) ),被称为“非线性”或Gamma corrected。 “线性” 值定义为
Rlin = R^gamma, Glin = G^gamma, Blin = B^gamma
许多PC的gamma为2.2。有时会写出通常的R G B. 作为R'G'B'(R'= Rlin ^(1 / gamma))(纯粹的舌头咔哒声)但是在这里 我会放弃'。
CRT显示器的亮度与RGBlin = RGB ^ gamma成正比, 所以CRT上的50%灰色很暗:.5 ^ 2.2 =最大值的22% 亮度。 (LCD显示更复杂;此外,还有一些图形 卡补偿伽马。)
要从RGB获得称为
L*
的亮度度量,首先除以R G. B乘255,并计算Y = .2126 * R^gamma + .7152 * G^gamma + .0722 * B^gamma
这是XYZ色彩空间中的
Y
;它是颜色“亮度”的量度。 (真正的公式不完全是x ^ gamma,但是接近;坚持 x ^ gamma用于第一遍。)最后, L * = 116 * Y ^ 1/3 - 16“...渴望感性均匀性......与人类对亮度的感知紧密相关。” - 维基百科Lab color space
答案 6 :(得分:1)
问题是“将像素的颜色淡化为白色”(不是一些灰色阴影),实际上是将原始像素颜色与白色混合,从100%原始颜色和0%白色变为0%原色和100%白色。没有更多的东西。例如,在101步骤中执行此操作将如下所示:
r0= 200; // as in the question
g0= 120;
b0= 40;
for(i= 100; i >= 0; i--){
r= (i * r0 + (100 - i) * 255) / 100;
g= (i * g0 + (100 - i) * 255) / 100;
b= (i * b0 + (100 - i) * 255) / 100;
// use this color (r, g, b) somehow
}
答案 7 :(得分:0)
@ mark-meyer的回答很好,我在StackMathematica部分用示例PartOne和Part Two.
详细回答了类似的问题对于此问题,渐变为全白,以下是使用我的渐变资源管理器的示例:
左列停留在sRGB中,下一个是线性xyY,然后是LAB,最右边是LAB L C h
您会注意到,在大多数情况下,保留在sRGB中与使用L*a*b*
并没有太大区别。部分原因是sRGB的伽玛曲线与LAB的感知曲线不同但相似。
您会注意到,虽然LCh版本具有某些色相变化,具体取决于起始颜色。如果是紫色,则需要在中间范围附近偏移一些。
对于LCh,色相旋转的方向(顺时针或逆时针)也会有所不同。
只看右边的LCh,这是洋红色的开始,没有偏移,并且自然旋转:
旋转方向相同,但有些偏移可平滑LCh梯度。
反转色相旋转和不同的偏移量,对于LCh,我们经过紫色而不是橙色:
这是黄色的,LCh在不调整色调偏移的情况下呈绿色:
但是抵消中间色调会平滑LCh梯度:
最后。使用L*a*b*
时,BLUE很棘手,因为它经常要转换为紫色。另一方面,在LCh中,蓝色想要转换为青色:
因此,实际上,通常您可以将sRGB留在sRGB中,以实现白色渐变,但是对于两种饱和颜色之间的渐变,您可能更喜欢使用LCh:
因此,在这里颜色之间的距离接近180°时,sRGB和LAB的中间值都变得不饱和,因为中间的平均值是灰色-sRGB的暗灰色和LAB的浅灰色。但是LCh保持饱和,而是通过色调旋转。