I am working on a project where I need to convert colors defined in RGB (Red, Green, Blue) color space to RYB (Red Yellow Blue).
I managed to solve converting a color from RYB to RGB space based on the article - Paint Inspired Color Mixing and Compositing for Visualization.
I convert a color from RYB to RGB with this "algorithm":
So the values of r (red), y (yellow), and b (blue) are known, also these arrays/sets are constants:
white: [1, 1, 1]
red: [1, 0, 0]
yellow: [1, 1, 0]
blue: [0.163, 0.373, 0.6]
violet: [0.5, 0, 0.5]
green: [0, 0.66, 0.2]
orange: [1, 0.5, 0]
black: [0.2, 0.094, 0.0]here is how I calculate the value of red for the RGB space based on the parameters above:
i = 1;
rgb_red = white[i] * (1 - r) * (1 - b) * (1 - y) +
red[i] * r * (1 - b) * (1 - y) +
blue[i] * (1 - r) * b * (1 - y) +
violet[i] * r * b * (1 - y) +
yellow[i] * (1 - r) * (1 - b) * y +
orange[i] * r * (1 - b) * y +
green[i] * (1 - r) * b * y +
black[i] * r * b * y);for rgb_green exactly the same thing but for i=2, and i=3 for rgb_blue.
My problem is that now I want to convert from RGB to RYB back. In other words, knowing the values of rgb_red, rgb_green and rgb_blue I want to calculate the values of r, y, and b. So I need a kind of inverse function for this, but I don't know how to get it.
Any help is appreciated.
$\endgroup$4 Answers
$\begingroup$Having read the linked paper, I now understand a lot more of what you are doing here than what you have explained. And I think I can help solve your problem.
The authors perform the conversion from RYB to RGB via a trilinear interpolation. In essence, they provide explicit values of a mapping from RYB to RGB on the corners of an RYB cube—i.e. every point $(r,y,b)$ where $r$, $y$, and $b$ are all $1$ or $0$—and they linearly interpolate along the three axes everywhere else.
Let us call that mapping $f: \textrm{RYB} \rightarrow \textrm{RGB}$, where $f$ takes an $(r,y,b)$ triplet to an $(R,G,B)$ triplet. (I will use lowercase for RYB and uppercase for RGB throughout.) The interpolation is defined by the following facts: $$\begin{align} \textrm{RYB}&\rightarrow\textrm{RGB}\\ f(0,0,0)&=(1,1,1)\\ f(0,0,1)&=(0.163, 0.373, 0.6)\\ f(0,1,0)&=(1,1,0)\\ f(0,1,1)&=(0, 0.66, 0.2)\\ f(1,0,0)&=(1,0,0)\\ f(1,0,1)&=(.5,.5,0)\\ f(1,1,0)&=(1,.5,0)\\ f(1,1,1)&=(0.2, 0.094, 0.0)\\ f(r,y,b)&=f(0,0,0)(1-r)(1-y)(1-b)+f(0,0,1)(1-r)(1-y)b\\ &\;+f(0,1,0)(1-r)y(1-b)+f(1,0,0)r(1-y)(1-b)\\ &\;+f(0,1,1)(1-r)yb+f(1,0,1)r(1-y)b\\ &\;+f(1,1,0)ry(1-b)+f(1,1,1)ryb \end{align}$$ where the subscript $c$ denotes a value at the corners.
You now want to solve the opposite problem. You want a function $f^{-1}: \textrm{RGB} \rightarrow \textrm{RYB}$ which takes a triplet $(R,G,B)$ to a triplet $(r,y,b)$. It seems to me that an easier problem to solve is to go through the same process as the authors of the linked paper did: find the RYB values of all the colors at the corners of an RGB cube and interpolate between them. This will give you a function $F: \textrm{RGB} \rightarrow \textrm{RYB}$ which might not be exactly equal to $f^{-1}$ but will hopefully be close enough for what you need.
$$\begin{align} \textrm{RGB}&\rightarrow\textrm{RYB}\\ F(0,0,0)&=?\\ F(0,0,1)&=?\\ F(0,1,0)&=?\\ F(0,1,1)&=?\\ F(1,0,0)&=(1,0,0)\\ F(1,0,1)&=?\\ F(1,1,0)&=(0,1,0)\\ F(1,1,1)&=(0,0,0)\\ F(R,G,B)&=F(0,0,0)(1-R)(1-G)(1-B)+F(0,0,1)(1-R)(1-G)B\\ &\;+F(0,1,0)(1-R)G(1-B)+F(1,0,0)R(1-G)(1-B)\\ &\;+F(0,1,1)(1-R)GB+F(1,0,1)R(1-G)B\\ &\;+F(1,1,0)RG(1-B)+F(1,1,1)RGB. \end{align}$$
The task that remains is to fill in those blanks. I would recommend coding up $f$ in something like Mathematica and finding the values $(r,y,b)$ where $f(r,y,b)=(R_c,G_c,B_c)$ for the values at the corners of the RGB cube. Then set $F(R_c,G_c,B_c)=(r,y,b)$ for the values you just found. Good luck!
$\endgroup$ 2 $\begingroup$When i wrote a program to convert between all majorly used color formats, i used the following algorithms for $RYB \rightarrow RGB$ and $RGB \rightarrow RYB$ conversion: (link to archive.org, original site is gone)
Now I don't know if this solution works perfectly with the conversion you already have, it looks like some kind of matrix multiplication. If we split $(1-r)(1-b)(1-y) = 1 - r - b - y + rb + ry + by -ryb$ we have 8 components. Also we have 8 components white[i], red[i], orange[i], yellow[i], ... so you can make it a matrix multiplication and add the values of the resulting vector to obtain $r$ (when $i=1$). Now to make an inverse matrix we need more information about the resulting vector. If we just add everything that is in the vector, we lose that information. I still think it is possible to do it with a matrix, but i dont know how to create one, other than making some assumptions like $\text{white}[i]=[1,1,1]$ (which i think will be for inverse as well), and explain why that would be true.
$\endgroup$ 1 $\begingroup$This is an old topic but I am just posting this for future reference, in case someone needs it.
I have looked for the RYB values corresponding to the colors at the corners of a RGB cube (the ? in Flavin's answer above). My process was:
- implement Gosset et al RYB to RGB conversion (i.e. what Tamàs did and the first part of Flavin's answer). This gives me RGB values that are easily digested by any color parsing function and can be displayed on screen.
- Define the colors of the corners of the RGB cube.
- For each corner, find the closest color in RYB space using:
- a perceptual color difference metric. I tried CIEDE2000 and CMC l:c; while CIEDE2000 is generally though to be superior, CMC l:c allows to weight chroma more than luminance which gave better results because what we designate as "color" is usually more related to chroma.
- either grid search on a table of colors computed with the function defined in (1) applied to a grid of R, Y, and B values or numerical minimisation of the color difference parameterised by the R,Y,B components (I used the Nelder-Mead algorithm). Both gave very similar results.
- Assign the RYB triplet to each corner.
Then I could perform the RGB to RYB conversion, computing each component by trilinear interpolation on this cube, exactly as defined by Flavin above.
The caveats:
- I changed the darkest RYB color compared to Gosset et al, to pure black, so that at least white and black are completely defined in each model;
- several colors are the corners of the RGB cube have no good equivalent in RYB space.
Here are the tables I ended up with:
RYB to RGB modified from Gosset et al
RYB 000 100 010 110 001 101 011 111 white red yellow orange blue purple green black
R 1 1 1 1 0.163 0.5 0 0
G 1 0 1 0.5 0.373 0 0.66 0
B 1 0 0 0 0.6 0.5 0.2 0RGB to RYB
RGB 000 100 010 110 001 101 011 111 black red green yellow blue magenta turquoi. white
R 1 1 0 0 0 0.309 0 0
Y 1 0 1 1 0 0 0.053 0
B 1 0 0.483 0 1 0.469 0.210 0and here is a representation of the colors at the corners of the RGB cube (top row) and the best matches in RYB space (bottom row): RGB to RYB match
$\endgroup$ $\begingroup$I want to sketch another approach which constructs a conversion functions between $RGB$ to $RYB$ color spaces. Especially I give a proper solution for conversion back to $RYB$.
First of all let's observe that $F: RYB\to RGB$ is an into function and transforms $RYB$ unit cube into a polyhedron included in the RGB unit cube. So we need to find a way to create $F^{-1}$ which transforms polyhedron to the $RYB$ cube.
To make this happen we can make the following:
- Decompose a cube into a six tetrahedra (this answer describes the coordinates and tests: )
- Create an affine transformation with the following procedure for finding a mapping between any two tetrahedra both ways, which is described:
Having above we will end up with six functions from $RYB$ to $RGB$ and another six functions from $RGB$ to $RYB$. One pair per each tetrahedron.
Now we face a problem of selecting proper mapping. For:
- $F$ we can use cube decomposition conditions
- $F^{-1}$ we need to figure out which tetrahedron contains given point. For that we can use barycentric coordinates (). Checking if all coordinates are positive is enough to be sure that tested point is inside given tetrahedron and which mapping to select ()
The last problem is: is it possible to find a mapping from whole $RGB$ cube into some extension of $RYB$ space? I think we can use the closest tetrahedron and its mapping. An open question is: which is the closest? Possibly that which has lowest sum of abs of barycentric coordinates.
EDIT: the above procedure has one disadventage, transition between colors is not smooth. Mainly due to not uniform transformation of tetrahedra.
The other approach I found is to use general barycentric coodinates. Wachspress coordinates are quite easy to calculate and transform. See:
- p. 11, 4.4 Barycentric mapping
- p. 26, 8 Coordinates in higher dimensions
in the following paper:
$\endgroup$ 1