How to fade color

I would like to put out the color of the pixel towards white, but obviously maintain the same color. If I have a pixel (200,120,40) , will add 10 to each value to make (210,130,50) make it the same color, just lighter or completely change the color? For example, I know that (100,100,100) going to (110,110,110) is a shade of gray. I would like it to be with RGB values, and I would like to do it numerically as indicated. Is there an equation?

+7
python colors image pixel image-processing
source share
8 answers

There are several ways to do this. How you decide to do this will depend on how much you value the speed and simplicity or uniformity of perception. If you need it to be truly uniform, you will need to define RGB colors with a color profile, and you will need profile primaries so that you can convert to XYZ and then to LAB, where you can manipulate the L channel.

In most cases, you do not need to do this, and instead you can use a simple HSB model, such as Photoshop, in the information palette.

To do this, you simply imagine the line between the RGB point and the white point in 3D space and move your color along this line. In practical terms, you can simply create a parametric equation for this line and move the parameter.

 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 

As a percentage of 0.0, the same color will be returned, and 1.0 will return to white. Everything between them will be a lighter shade of the same shade. This should give you results that are consistent with the implementation of Photoshop HSB, but will be device dependent and may not be completely uniform.

If you have RGB [200, 100, 50] and fit in a percentage value of 0.50, it should return at least 20º of RGB[ 227.5 177.5 152.5] Photoshop.

It is easy to do this without numpy, but convenient operations with elements.

Edit based on comment:

I do not suggest that you do this if you do not know that you really need to do this. But if you want to convert to LAB, you can without any problems. Most importantly, you need to know what color space you need for RGB numbers, or you need to make some assumptions about their meaning. Since sRGB is pretty standard on the Internet, I will assume that here.

Conversions are not so difficult, but it’s easy to make mistakes. Fortunately, there is a nice colormath module with good documentation: https://github.com/gtaylor/python-colormath

Using this, you can convert between sRGB and LAB as follows:

 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) 
Laboratory

now represents a color with the Luminance lab.lab_l channel, which can be moved up or down between black (0) and white (100). This should be more susceptibly consistent than HSB (but, depending on your application, it may not be enough to guarantee operation).

You can just change lab_l and then convert back:

 lab.lab_l = 80 new_sRGB = convert_color(lab, color_objects.sRGBColor).get_upscaled_value_tuple() 

new_sRGB now [198, 198, 198] . colormath took care of the lighting and gamma problems for you.

+15
source share

Just linearly interpolate between your color and white:

 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) 

Or without numpy:

 lightened25 = [lerp(c, w, 0.25) for c, w in zip(my_color, white)] 
+5
source share

I prefer to use HSV color mode .

To reduce your color, you need to reduce the saturation factor.

The standard colorsys module can help with RGB ↔ HSV conversions, but keep in mind: colorsys works with the value channel in the range [0, 1), not [0, 256].

There is a complete code:

 >>> 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) 
+4
source share

This is not so simple because on your monitor each color channel is weighted differently. I would say that it’s best to do this in a scikit image by switching to gray, dimming or brightening, and then converting back to color. Scikit-image will take care to keep colors straight.

 from skimage.color import gray2rgb, rgb2gray scale_factor = 0.9 #90 percent img_new = gray2rgb(rgb2gray(img) * scale_factor) 

If you want to work directly with hue, saturation and value, see this example:

http://scikit-image.org/docs/dev/auto_examples/plot_tinting_grayscale_images.html

+2
source share

As suggested by MarkM, HSB (or HSL) is an easy way to do this, but will not give an ideal constant shade. If this is good enough (I assume you want your own method instead of a module), then this page has code for this.

In python, it will look like this:

 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 

Then, to brighten up:

 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)) 

The advantage of this method is that the increment is a percentage of the total brightness. Changing this value to enter a percentage as input would be trivial.

You can rebuild the mathematical equations from this code or look at HSL on RGB .

+2
source share

You can check this denis answer :

RGB → ^ gamma → Y → L *

In color science, common RGB values, like html rgb (10%, 20%, 30%), are called "non-linear" or Gamma corrected . Linear values ​​are defined as

 Rlin = R^gamma, Glin = G^gamma, Blin = B^gamma 

where gamma is 2.2 for many PCs. Regular RGB is sometimes written as R 'G' B '(R' = Rlin ^ (1 / gamma)) (purists speak English), but here I will throw it out. '

The brightness on the CRT display is proportional to RGBlin = RGB ^ gamma, so 50% gray on a CRT is quite dark: .5 ^ 2.2 = 22% of the maximum brightness. (LCDs are more complex, and some graphics on the card compensate for gamma.)

To get a measure of lightness called L* from RGB, first divide RGB by 255, and calculate

 Y = .2126 * R^gamma + .7152 * G^gamma + .0722 * B^gamma 

This is Y in the XYZ color space; it is a measure of color "brightness." (The real formulas are not exactly x ^ gamma, but close, stick to x ^ gamma for the first pass.)

Finally, L * = 116 * Y ^ 1/3 - 16 "... strives for a uniform perception ... closely corresponds to a person's perception of lightness." - Wikipedia Lab color space

+1
source share

The question is “to fade the color of the pixel toward white” (not some shade of gray), actually mixing the original pixel color with white, based on 100% of the original color and 0% white to 0% original color and 100% white. There is no more. Doing this, for example, 101 steps will look like this:

 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 } 
+1
source share

@ mark-meyer the answer is good, I answered a similar question in the StackMathematica section in great detail with examples of PartOne and Part Two.

For this question, from gradient to full white, here are examples using my gradient researcher:

The left column remains in sRGB, the next is linear xyY, then LAB, and the rightmost is LAB LCh.

enter image description here

You will notice that in most cases, saving to sRGB is not significantly different from using L*a*b* . This is partly because sRGB has a gamma curve that is different but similar to the LAB perception curve.

However, you will notice that the LCh version has some hue shifts depending on the initial color. In the case of magenta, this requires some offsets near the mid-range.

Also with LCh, the direction (clockwise or counterclockwise) of the hue rotation matters.

If you look only at the right LCh, here is the purple start without offsets and the natural rotation:

enter image description here

The same direction of rotation, but some offsets to smooth out the LF gradient.

enter image description here

Changing the hue direction and various offsets, we see purple instead of orange for LCh:

enter image description here

And here from yellow, LCh gets a green hue without adjusting the hue offset:

enter image description here

But a midtone shift smooths the LCh gradient:

enter image description here

And finally. BLUE is difficult with L*a*b* as he often wants to switch to purple. On the other hand, in Champions League blue wants to switch to blue:

enter image description here

So you can actually stay in sRGB for things like gradients to white, but for gradients between two saturated colors, you might prefer to use LCh:

enter image description here

So here, where the colors are 180 ° closer to each other, the middle becomes unsaturated for both sRGB and LAB, as the average in the middle is gray - a darker cloudy gray for sRGB and lighter gray for LAB. But the Champions League retains saturation and instead rotates through shades.

0
source share

All Articles