Converting RGB to individual decimal values - colors

I have Red, Green, and Blue values being represented as decimal values. I need to be able to convert them to a color (like a standard RGB 255, 255, 255 or HSV or HSL).
For example:
Red = 0.7
Green = 0.8
Blue = 0.7
would result in a "Green" color
Red = 5.00
Green = 0.50
Blue = 0.00
would result in a "Redish/Brown" color
I've tried to do basic conversion to RGB (0-255, 0-255, 0-255) and nothing really maps correctly given that the intensity of colors increase above a decimal value of 1.0 So I'm very puzzled on how I can convert these decimal values to match up with an RGB color chart?
The values seem to work more like a "Color mixer" ... the higher the decimal value the more "Bright/intense" the color.
For example:
Red = 10.0
Green = 10.0
Blue = 10.0
results in an off white, but
Red = 40.0
Green = 40.0
Blue = 40.0
results in a very bright white
But I can't seem to figure out how to calculate a conversion from these decimal value to a RGB standard color chart value (and visa-versa)?
Any suggestions?

Related

how to convert CIE color in the following format x = 0.615, y = 0.346, 5.6 cd/m2; to HEX or RGB

Iv'e found converters from xyz, and posts that talk about that posts . but couldnt find a good reference for the 'cd/m2' component of the color
The coordinates you are giving in the question are CIE xyY (small x, small y, BIG Y), they are not CIE XYZ Tristimulus Values (BIG X, BIG Y, BIG Z). The commonality between the two is the Luminance Y. CIE xyY is a perspective projection from CIE XYZ along the Luminance Y-axis to separate Luminance and Chrominance information.
To convert from CIE xyY to HEX or RGB (sRGB) you need to follow the following path:
CIE xyY --> CIE XYZ --> RGB --> HEX
Using Colour, this transformation would be expressed as follows:
import colour
xyY = [0.615, 0.346, 5.6]
XYZ = colour.xyY_to_XYZ(xyY)
RGB = colour.XYZ_to_sRGB(XYZ, apply_cctf_encoding=False)
print(RGB)
RGB_n = colour.utilities.normalise_maximum(RGB)
print(RGB_n)
print(colour.notation.RGB_to_HEX(colour.cctf_encoding(RGB_n)))
[ 23.33310243 0.88648 0.07921734]
[ 1. 0.03799238 0.00339506]
#fe360b
or using the Automatic Colour Conversion Graph as of latest develop branch:
import colour
xyY = [0.615, 0.346, 5.6]
print(colour.convert(xyY, 'CIE xyY', 'Hexadecimal'))
.../colour/colour/utilities/verbose.py:237: ColourUsageWarning: "RGB" array contains values over 1 and will be normalised, unpredictable results may occur!
warn(*args, **kwargs)
#fe360b
Note that because your colour is High Dynamic Range (HDR), i.e. Y = 5.6, it cannot be converted to Hexadecimal representation without a normalisation process before converting from RGB to Hexadecimal. Here the colours are normalised so that the maximum RGB value is 1 but it is also worth considering that you are using sRGB colours and divide Y by 80 which is the typical sRGB display peak luminance.

plotting "with impulses" using multiple fields from an input file

sample "input file":
x y1(red) y2(blue) y3(green)
10 0.08 0.02 0.90
15 0.03 0.90 0.07
20 0.85 0.10 0.05
My x-axis is 10, 15, 20, or column 1 in the sample input file. Columns 2-4 are my dependent variables, labeled by color. The x-axis is distance; the y-axis is impulse signal.
goal
I would like a graph plotted as "x:y with impulse", or something equivalent. My output would appear like:
x = 10 15 20
green 0.90 0.07 0.05
red 0.08 0.03 0.85
blue 0.02 0.90 0.10
At x = 10, I would see a green line with an intensity of 0.90, overlapped by a red line with an intensity of 0.08, followed by a blue line with intensity 0.02. I can tell at a glance that for x=10, my parameter is 90% green, 8% red, and 2% blue.
For x=15, I would have a blue line with an intensity of 0.90, a green line with an intensity of 0.07, and a red line with intensity 0.03.
and similar for x = 20.
In other words, my goal is to see, for a given x-value, exactly what percentage contributions my three dependent variables have.
problem
Currently, I can do something like
plot "input file" u 1:4 w i lc rgb "green"
replot "input file" u 1:3 w i lc rgb "blue"
replot "input file" u 1:2 w i lc rgb "red"
Unfortunately, the most recent replot will overlap and cover up any previous plots of smaller impulse.
With this approach, my plot would look like:
x = 10 15 20
green 0.90 ---- ----
red 0.08 0.03 0.85
blue ---- 0.90 ----
I would only see green at x = 10, and blue only at x = 15. Because red is replotted last, it overlaps and covers the other colors due to having a greater intensity. I can see red perfectly at all three x-values, but I lose green and blue.
Is there maybe a way to tell replot to not overshadow previous plots? Or an alternative approach to replot to achieve the goal stated above?
summary
I am trying to plot a multi-field input at each point x, while preserving the original legend label in my key for each column.
In my actual case, I have anywhere from 8-40 fields, across a few hundred x values, so I can't simply input manually which columns I'd like where.
Any assistance is greatly appreciated. I am open to any solutions, even a different software if gnuplot cannot do this.
set linetype 1 lc "green"
set linetype 2 lc "red"
set linetype 3 lc "blue"
unset key
set yrange [0:1]
set style data histogram
set style histogram cluster gap 3
set style fill solid
plot for [col=2:4] 'inputfile' using col:xticlabel(1)

How to define BGR color range? Map color code to color name

I want to create color mapping, define few color names and boundaries in range of which those colors should fall. For example (BGR format),
colors = {
'red': ((0, 0, 255), (125, 125, 255)),
'blue': ((255, 0, 0), (255, 125, 125)),
'yellow' ....
}
So if I receive color, let's say (255, 50, 119) I can call it blue. I want to make such mapping for at least colors of rainbow plus gray, black, white. Using Python and openCV.
The problem is that I don't really understand where to get those values for boundaries, is there kind of lowest / highest value for blue, red and so on?
I would suggest using HSV colourspace for comparing colours because it is less sensitive to variable lighting than RGB, where green in the sunlight might be rgb(20,255,10), but green in a shadow might be rgb(3,45,2), whereas both will have a very similar Hue in HSV colourspace.
So, to get started...
Create a little 10x1 numpy array and make the first pixel red, the second orange, then yellow, green, blue, indigo, violet then black, mid-grey and white. There's a table here.
Then convert to HSV colourspace and note the Hue values.
I have started some code...
#!/usr/local/bin/python3
import numpy as np
import imageio
import cv2
# Create black image 10x1
im = np.zeros([1,10,3], dtype=np.uint8)
# Fill with colours of rainbow and greys
im[0,0,:]=[255,0,0] # red
im[0,1,:]=[255,165,0] # orange
im[0,2,:]=[255,255,0] # yellow
im[0,3,:]=[0,255,0] # green
im[0,4,:]=[0,0,255] # blue
im[0,5,:]=[75,0,130] # indigo
im[0,6,:]=[238,130,238] # violet
im[0,7,:]=[0,0,0] # black
im[0,8,:]=[127,127,127] # grey
im[0,9,:]=[255,255,255] # white
imageio.imwrite("result.png",im)
hsv=cv2.cvtColor(im,cv2.COLOR_RGB2HSV)
print(hsv)
Check image:
Check colours with Imagemagick too:
convert result.png txt:
# ImageMagick pixel enumeration: 10,1,65535,srgb
0,0: (65535,0,0) #FF0000 red
1,0: (65535,42405,0) #FFA500 orange
2,0: (65535,65535,0) #FFFF00 yellow
3,0: (0,65535,0) #00FF00 lime
4,0: (0,0,65535) #0000FF blue
5,0: (19275,0,33410) #4B0082 indigo
6,0: (61166,33410,61166) #EE82EE violet
7,0: (0,0,0) #000000 black
8,0: (32639,32639,32639) #7F7F7F grey50
9,0: (65535,65535,65535) #FFFFFF white
Now look at the HSV array below - specifically the first column (Hue). You can see Red has a Hue=0, Orange is 19, Yellow is 30 and so on. Note too that the Black, Grey and White all have zero Saturation and Black has a low Value, Grey has a medium Value and White has a high Value.
[[[ 0 255 255]
[ 19 255 255]
[ 30 255 255]
[ 60 255 255]
[120 255 255]
[137 255 130]
[150 116 238]
[ 0 0 0]
[ 0 0 127]
[ 0 0 255]]]
Now you can make a data-structure in Python that stores, for each colour:
Lowest included Hue
Highest included Hue
Name
So, you might use:
... see note at bottom for Red
14,23,"Orange"
25,35,"Yellow"
55,65,"Green"
115,125,"Blue"
...
and so on - omit Black, Grey and White from the table.
So, how do you use this?
Well, When you get a colour to check, first convert the R, G and B values to HSV and look at the resulting Saturation - which is a measure of vividness of the colour. Garish colours will have high saturation, whereas lacklustre, greyish colours will have low saturation.
So, see if the Saturation is more than say 10% of the max possible, e.g. more than 25 on a scale of 0-255.
If the Saturation is below the limit, check the Value and assign Black if Value low, Grey if middling and White if Value is high.
If the Saturation is above the limit, check if it is within the lower and upper limits of one of your recorded Hues and name it accordingly.
So the code is something like this:
def ColorNameFromRGB(R,G,B)
# Calculate HSV from R,G,B - something like this
# Make a single pixel from the parameters
onepx=np.reshape(np.array([R,G,B],dtype=np.uint8),(1,1,3))
# Convert it to HSV
onepxHSV=cv2.cvtColor(onepx,cv2.COLOR_RGB2HSV)
...
...
if S<25:
if V<85:
return "black"
elsif V<170:
return "grey"
return "white"
# This is a saturated colour
Iterate through colour names table and return name of entry with matching Hue
There are 2 things to be aware of:
There is a discontinuity in the Hue values for Red, because the HSV colour wheel is a circular wheel and the Hue value for Red is at an angle of 0, so values above 350 and below 10 are all Reds. It so happens that OpenCV scales the 0-360 range by dividing by 2, meaning it comes out as 0-180... which neatly fits in a single unsigned byte. So, for Red, you need to check for Hue greater than 175 and less than 5, say.
Be careful to always generate an 8-bit image when looking up colours, as the Hue values are scaled differently on 16-bit and float images.
Define a distance between two colors. Then find the "closest" color name for the given color. Which definition of distance you will choose has to be guided by your requirements, because there is no "best" definition, as far as I know.
One possibility is distance in RGB space. The distance between two colors can be defined, for example, as the euclidean (L2) distance between the colors as represented by vectors in three dimensional space - distance(a,b) = (a-b).length() Alternatively, try the Manhattan (L1) metric if the result makes sense, because the euclidean distance in RGB space is more of a heuristic than a valid measurement.
Another possibility is to first convert to HSV space. Then the closest color will be the one that has the closest hue to the given color. Unless the given color has insufficient saturation, then the color is either white, gray or black, depending on the color's lightness.

Create a false color palette and associate pixel values with it

I have raw pixel data (640x480 pixels) from an infrared camera which stand for a specific measured temperature. These pixel values have a 16 bit range from 0 to 65535.
I can display the pixel values as 8 bit greyscale, which works very well.
But now I want to display those pixels by using a false color palette.
I noticed 2 challenges here:
1.) Creating a false color palette. This means not just a simple RGB or HSV palette...I am thinking of a transition from black to yellow, to orange, to red and finally to purple
2.) Associating the pixel values to a color on my palette (e.g. 0 = black, 65535 = purple, but 31521 = ???)
Do you have an idea how I should approach this problem? I use Qt4 and Python (PyQt) but also I would be very happy if you just share the way for a solution.
One simple way would be to define colors at certain points in your range - as in your example, 0 is black, 65535 is purple, maybe 10000 is red, whatever you want to do. Set up a table with those key rgb values, and then simply interpolate between the rgb values of the key values above and below your input value to find the rgb color for any given value.
eg. if you're looking up the color for the value 1000, and your table has
value=0, color=(0,0,0)
value=5000, color=(255, 0, 255)
Then you would interpolate between these values to get the color (51, 0, 51)
The easiest method is as follows:
Cast your unsigned short to a QRgb type, and use that in the QColor constructor.
unsigned short my_temp=...;
QColor my_clr((QRgb)my_temp);
This will make your values the colors between black and cyan.

how to calculate gradient color by percent

I have a float score, which is 0 to 1
I need translate this score to color,
0 is green
1 is red
0.5 should at the middle of green to red gradient color
and so on
how to write this? I have no idea.
let gradient colour parameter be t, 0.0 =< t =< 1.0
colour = RGB(255 * t, 255 * (1 - t), 0)
Multiply the float by 255 to get your green value, and multiply (1-float) by 255 to get your red value. If you need to output a css color code, use rgb(x,y,z).

Resources