# Compute opponent colour of RGB values

26 views (last 30 days)
Devin on 25 Jan 2011
Edited: Walter Roberson on 19 Sep 2021
I'm looking for a script in which I can compute the RGB values corresponding to the opponent color of another set of RGB values.
So, I would provide the three RGB values for a colour (e.g., red) and then get the RGB values for the opponent colour (green).
Any thoughts/suggestions on this, would be great.
Walter Roberson on 25 Jan 2011
Please define what you mean by "opponent colour". Is that the Gaussian Color model, such as is illustrated in
Would it be sufficient to use CIE 1964 and the transformation shown on page 9 of the above pdf?

the cyclist on 25 Jan 2011
I think, but I am not sure, that you are talking about the "complementary" color.
If your RGB color vector is [r g b], where each value is in the range [0,1], then I believe your complementary color vector is ([1 1 1]- [r g b]).
Note, the complement of red is cyan, not green, so maybe I just misunderstand your question.
Adam Danz on 19 Sep 2021
Thanks for the demo @Image Analyst. I'll have to look into the differences between that and imcomplement.
subplot(1,2,1);
imshow(rgbImage);
title('Original RGB Image');
newRGBImage = imcomplement(rgbImage);
subplot(1,2,2);
imshow(newRGBImage);
title('New RGB Image'); Kenneth Eaton on 25 Jan 2011
If you are talking about a color opponent process, I figured out a simple function that will compute opponent colors for the six colors involved in the three opponent channels: black vs. white, red vs. green, and blue vs. yellow:
opp_color = @(c) [~c(1:2) ~c(3).*~xor(c(1),c(2))];
Given one of the six colors, it will return the opponent color. Here is a test where I have generalized opp_color to operate on rows of an input N-by-3 matrix of colors:
>> opp_color = @(C) [~C(:,1:2) ~C(:,3).*~xor(C(:,1),C(:,2))];
>> cmat = [0 0 0; 1 1 1; 1 0 0; 0 1 0; 0 0 1; 1 1 0]; % Six colors
cmat =
0 0 0
1 1 1
1 0 0
0 1 0
0 0 1
1 1 0
>> opp_color(cmat) % Opponent colors
ans =
1 1 1
0 0 0
0 1 0
1 0 0
1 1 0
0 0 1
This of course only works for these six colors. I don't know exactly how the theory works for lighter or darker versions or for mixtures of colors, but maybe this will still be useful to you. ;)
EDIT:
Here's a different version of the function opp_color, still only applicable to the six colors given above:
opp_color = @(C) (1-C).*[ones(size(C,1),2) C(:,1)==C(:,2)];
Walter Roberson on 25 Jan 2011
Unfortunately this is not extensible to fractional colors. The ~ could possibly be replaced by subtraction from 1, but the equivalent to the xor is not obvious.

Walter Roberson on 26 Jan 2011
I approached this as a system of simultaneous equations that had to be satisfied. For example, it is not as easy as Red being in opposition to Green, as Red and Green combine to make yellow and we have to make the yellow opposite to the Blue.
I had to make some assumptions about how to measure "yellowness"; I decided to use the geometric mean of red and green, sqrt(R*G). Possibly min(R,G) would be a better measure, but one more difficult to work with analytically.
For black versus white, I used the typical luminance, 0.3*R + 0.59*G + 0.11*B and assumed that "blackness" is 1 minus the luminance.
I used R, G, B in the 0 to 1 range.
Proceeding symbolically in Maple with R0, G0, B0 being the initial values, and R1, G1, B1 being the complimentary values, I defined
L := (R, G, B) -> (3/10)*R+(59/100)*G+(11/100)*B;
and then
solve({R0-G0 = G1-R1, sqrt(R0*G0)-B0 = B1-sqrt(R1*G1), L(R0, G0, B0) = 1-L(R1, G1, B1)}, [R1, G1, B1]);
this resulted in an expression with some resolvable quadratics. Expanding the quadratics and collecting terms, I got
S := sqrt(40000 - 8800*sqrt(R0)*sqrt(G0) - 35600*G0 - 35600*R0 + 31926*R0*G0 + 3916*sqrt(R0)*G0^(3/2) + 3916*R0^(3/2)*sqrt(G0) + 121*G0^2 + 121*R0^2);
[
R1 = -(15721/15600)*R0 - (121/15600)*G0 + 89/78 - (979/7800)*sqrt(R0)*sqrt(G0) + (11/15600)*S
G1 = 89/78 - (979/7800)*sqrt(R0)*sqrt(G0) - (15721/15600)*G0 - (121/15600)*R0 + (11/15600)*S
B1 = (979/15600)*G0 - B0 - 11/78 + (7921/7800)*sqrt(R0)*sqrt(G0) + (979/15600)*R0 - (89/15600)*S
]
and
[
R1 = -(15721/15600)*R0 - (121/15600)*G0 + 89/78 - (979/7800)*sqrt(R0)*sqrt(G0) - (11/15600)*S
G1 = 89/78 - (979/7800)*sqrt(R0)*sqrt(G0) - (15721/15600)*G0 - (121/15600)*R0 - (11/15600)*S
B1 = (979/15600)*G0 - B0 - 11/78 + (7921/7800)*sqrt(R0)*sqrt(G0) + (979/15600)*R0 + (89/15600)*S
]
In testing these out, the second set produces reasonable answers more often than the first. Both sets produce unreasonable answers for some triples: presumably my model of "yellowness" computed from the RGB triple is flawed.

Devin on 26 Jan 2011
Greetings. Thanks for all of your responses. Yes, I was referring to the opponent color - so I did mean green as the opponent to red. It seems that Walter's script is getting quite close, but as you mention it still has some flaws. Kenneth, thanks for your response as well. We will actually be needing to compute the opponent RGB value for a large variety of different colors, so six, as you sugggest, would be too small of a pool.
If anyone else has any ideas I would be appreciative.
cheers, Devin

shima on 27 Feb 2011
hello guys...
im doing a research on image processing to find the most suitable technique to get the range of red color... as i do not have any background on image processing please tell me what are different techniques of color detection? thank you
Walter Roberson on 27 Feb 2011
Hi, I see you have created a new Question for this topic, as is appropriate, as it does not have anything to do with the opponent color process.