Here’s a script I wanted to write: given a color c specified in RGB and an angle θ, rotate c on the color wheel by θ and return the RGB value of the result.
You can’t rotate RGB values per se, but you can rotate hues. So my initial idea was to convert RGB to HSV or HSL, rotate the H component, then convert back to RGB. There are some subtleties with converting between RGB and either HSV or HSL, but I’m willing to ignore those for now.
The problem I ran into was that my idea of a color wheel doesn’t match the HSV or HSL color wheels. For example, I’m thinking of green as the complementary color to red, the color 180° away. On the HSV and HSL color wheels, the complementary color to red is cyan. The color wheel I have in mind is the “artist’s color wheel” based on the RYB color space, not RGB. Subtractive color, not additive.
This brings up several questions.
- How do you convert back and forth between RYB and RGB?
- How do you describe the artist’s color wheel mathematically, in RYB or any other system?
- What is a good reference on color theory? I’d like to understand in detail how the various color systems relate, something that spans the gamut (pun intended) from an artist’s perspective down to physics and physiology.
I have just bought “Art and Visual Perception” by Rudolf Arnhem and “Interactions of Color” by Josef Albers. They have only just arrived so I haven’t started reading them yet, and perhaps more on the art side, but might be interesting.
I’m afraid what you want to do could not be done based on purist mathematics, but rather in a heuristic remapping of “the colors you want” to “the colors that actually are”, so to speak.
From the very Wikipedia article on RYB, it’s implicit that this model is not proportional, but instead based in a somewhat arbitrary choice of primary colors, that would then be put 120 degrees apart in a colorwheel.
As an interesting note, the reason why all human color systems are tridimensional is because we have three color receptors in the retina, which are R, G and B.
Also, as far as I remember, Wikipedia has abundant resources on color theory, but reading the articles to the point of understanding what’s really involved is quite exhausting.
I think the easiest way to do the rotation is to calculate a ryb-like hue value (H’) and rotate that, so it’ll go RGB -> HSV -> H’SV –(rotate H’)-> H’SV -> HSV -> RGB. Normal hue (H) is yellow at 60 and green at 120, while ryb-like hue (H’) is yellow at 120 and green at 180, so the formula for H’ is H*2 when H<60, H+60 when 60<H<120, 240-(240-H)/2 when 120<H240.
I think you’ll get RYB if you use HSV2RGB on a H’SV color.
Quantifying perception is very complicated. Even quantifying a single person’s perception is complicated, without taking into account variations between people. It’s surprising that it can be done at all. And yet it can be, at least to a useful approximation. The artist’s color wheel is somewhat arbitrary, but there’s a broad consensus that it is “right” in some sense. People generally agree, for example, on what colors are complementary.
I’ve looked into audio perception fairly deeply, but not visual perception. We naively talk about one sound being twice as loud as another. Then on closer inspection it seems hopeless to quantify such a statement. But then on even closer inspection, you find there actually is broad agreement on when one sound is twice as loud as another. It’s a horribly nonlinear function of sound components, but most people come to approximately the same judgments.
This book:
https://www.amazon.com/Human-Color-Vision-Peter-Kaiser/dp/1557524610
was the “bible” on this sort of thing for many years, I think.
There seem to be PDFs of various parts of it online.
One thing: Are you sure you want a system based on subtractive color? Opponency-based systems have red and green on opposite “sides” of the space also. So, for instance, L*a*b* or L*c*h* might do what you want. Those are also designed to be (roughly) perceptually uniform.
It would have to be some kind of non uniform mapping, because the artist’s color wheel is defective. Cyan really is a complement to red in a way that green isn’t. Green’s complement is magenta, and blue’s complement is yellow. That’s why printing uses CMY (or CMYK, to sidestep the problem that if your C, M, and Y aren’t perfect, adding them all together will make a poor black), not RYB. RGB is an additive space, CMY is a subtractive space, RYB is a bastard.
Lab color space chromaticity planes seem to be closer to the artist’s color wheel than HSV or HSL, so my suggestion is to transform the RGB color to Lab color space, rotate the chromaticity coordinates a and b around the origin for the given angle, keep L constant, and transform the resulting color back to RGB.
Lab color space was intended to be perceptually uniform color space where the Euclidean metric would measure the perceived distance between colors. However, other metrics on Lab space have been found to be more accurate to define the “geodesics of color perception”.
Lab is a commonly used perceptually uniform space, for what it’s worth, which makes it a good intermediate space sometimes. L for lightness, a and b are the principal components of colorfulness, and one unit in any direction is the same perceived difference as in any other direction.
Of course, since it’s perceptually uniform (nearly) and other spaces aren’t, you can run into the problem where you convert RGB to Lab, find a complement by inverting a and b, try to convert back to RGB, and find that the color you ended up with requires a negative amount of some color, or more than 100%. Then you have to map to some nearby color that you can represent, choosing which property to preserve (generally, either lightness or saturation, but you can’t have both). The fun of nonlinear transforms.
The color receptors in the eye are RGB, so imagine a triangle with R, G, and B in the vertices. On the edges are C, M, and Y. You can now create a new triangle with R, Y, and B. This triangle is much smaller than the original. And, indeed, so is the artist’s color wheel. (You can’t reach cyan, but artists apparently don’t care about cyan.)
It should be clear now how to do what you want: Find the color in the RGB space, clamp it to the RYB sub-triangle, encode that as an angle using the same algorithm as HSV, rotate, and convert back. It’ll be lossy because the primaries you’re choosing aren’t as far apart as RGB.
(The whole truth about the artist’s color wheel is more complex, and in fact when they say “blue” they pick a very greenish blue, and in fact their primaries are subtractive, etc.)
My worlds are colliding…I just read this article. Maybe something here will send you down a rabbit hole that helps.
http://99percentinvisible.org/article/color-sphere-professors-pivotal-color-space-numbering-system/
As a painter in both physical and digital media, I to have attempted to think out how to make use of the various color measurement systems and find how they correspond.
Lacking a simple all encompassing answer, I can tell you that a two dimensional color wheel that artist use is more of a suggestion as to how color works, does not and will never relate to ryb nor rgb. The essential reason for this is that color is best thought of and represented in three dimensions. In the case of rgb, 256 x 256 x 256 is three dimensional. Its not a color wheel but a color ball. Human sight turns it a lopsided one with more green than anything else and not so much yellow in it. Any representation of the rgb space will demonstrate that it is three dimensional.
I could imagine the ryb space accurately working the same way were it not for resonance of other hues and tints existing in the substance we are working with, paint as an example. So called impurities in the material reflecting multiple hues and tints are why the paint store has multiple shades of the tinting colors in their paint tinting machine, why we buy 9 inks for our printer instead of 3. So, without having a measurement of the materials being used to produce the required color, you are lost. Your math has no point upon which it can begin to make comparison.
RGB, however,can reliably start a formula anywhere along its 256 x 256 x 256 range of possibilities.
A lot of typing just to say im not sure your goal can be done. Id like to see it if you do prove successful.
The problem described is such a good producer of fun to think of heuristics, and color is so colorful, so I had to pitch in my idea:
a) Choose three pairs of colors you’d like to be opposite (e.g. Green/Red). It could be more than three, but it seems enough.
b) Find a good representation of color space (from color-smart packages). These usually allow interpolation between colors. Find the colors from step (a) in the space.
c) Concoct a good way to project colors onto a line between two colors in the color space.
d) Imagine the Cook color space as a 3-torus, with one dimension for each color pair and the pair on opposite sides (surely the easiest step).
e) To rotate color A:
1) project it on the three color lines (between color pairs).
2) rotate by \theta in each dimension.
3) recover a color by adding the three rotations in the same proportions as the projection (i.e. less if color A was far from the line).
4) the recovered color is the output.
f) (*optional) write a paper/package/talk/TED-talk about it.
David, that is a splendid solution! I wish there was a like button!
The underlying problem is that ALL color “spaces” are imperfect projections through imperfect model(s) of human color perception.
First, nearly all of them assume “large area uniform perception”, ignoring perceptual effects like gradients, edges and mixtures due to lighting or shadows. Also ignoring issues such as metamerism.
Having worked on digital video camera design and implementation (circa 2000), and particularly on issues of color “fidelity”, I had to perform full visual spectrum transforms all the way from the subject, through the lens, through the sensor’s micro lenses, Bayer filters and silicon, through analog circuit signal filters, ADC, digital filters, digital encoders, and THEN through the monitor’s digital decoder, digital filters, DAC, analog filters and pixel drivers to the LCD element, its color filter, and the backlight and polarizers.
I got lots of spectrophotometer and spectroradiometer experience. I did lots of testing with nearly-monochromatic (narrow spectrum) color sources as well as broadband sources with various white points.
It was a ton of modeling work that, in the end, got me nowhere. I finally punted into the sRGB color space. And even in that limited color space, with our best theoretical camera, graphics card and and monitor color calibrations all in place, we still had many subject colors that looked very different on the monitor.
We finally wound up where everyone else in the industry did (at that time): Shoot the GretagMacbeth ColorChecker 24 and create the transforms needed to make those specific color patches render correctly on the monitor. And let all other colors fall where they may.
So, when asked about what color is X distance away from a given color, I always ask: With what camera, monitor and graphics card or printer? With which color corrections in place? Under what illumination conditions? For which viewer(s)?
All else is approximate in the extreme. So pretty much any honest guess will be “good enough” for most folks without a spectrophotometer in their pocket.
But, as others have said, working in/through the L*a*b* (CIELab) color space is probably best overall.
https://graphics.stanford.edu/~boulos/papers/orgb_sig.pdf
Here’s a codepen that shows what RYB looks like if you do it by altering the hue (like I commented earlier): https://codepen.io/sjoerdvisscher/full/jwOOXW/
At the top there’s a test of calculating the complementary colors, below that are the 6 sides of the RYB color cube where I’ve reduced the intensity of cyan by 40% to make the gradients look smooth.
An excellent online resource is http://www.brucelindbloom.com/ “color scientist”.
BTW I wrote a Python color module implementing most of the conversions and several operations on colors. Demo notebook is here : http://nbviewer.jupyter.org/github/Goulu/Goulib/blob/master/notebooks/colors.ipynb and code is here : https://github.com/goulu/Goulib .
I’ll add your rotation code if you don’t ;-) Thanks !
I’m a bit late, but here’s a resource with LOTS of information about human perception, color, color spaces, etc.: http://www.handprint.com/LS/CVS/color.html
Feel free to forward the link https://area51.stackexchange.com/proposals/110687/color-theory
to anyone who might be interested in this fascinating field of study.