How could I display a "circle at the bottom of the figure? And color it along the way? To show Hue angles?

13 views (last 30 days)
Crazy idea. I know Matlab is calling OpenGL under the hood but I would not know how to go about adding these two pieces of geometric elements to my chart. What follows is a "mock-up", to show what I'm trying to achieve :
You have my 3D figure, showing a custom datatip. What I would like to add is a "3D plot" (I guess?) that sits at the bottom of the chart, I get using some kind of colormap, to simulate a continuous drawing? The idea is to represent "Hue angle" on this chart, To show it through a "color wheel" and some kind of "black line" drawn along the hue angle, to show the students how to interpret visually the notion that color can have an "angle".

Accepted Answer

DGM
DGM on 5 Mar 2022
Edited: DGM on 5 Mar 2022
The problem that I'm seeing with the answers so far is that they're not going to be projected correctly into the color space in use.
If you do something using a plain HSV sweep, you'll get something that aligns like this. I stacked the ring on top so it's easy to tell that it's misaligned.
Obviously, the projection of the corners of the RGB cube are no longer spaced by equal angles in LAB. You need to actually project that color sweep into the space you're using.
This is an example
% parameters
npoints = 1000;
radius = 100;
% get a cyclic rgb color map
CTrgb = hsv(npoints);
% project it into the desired space, set radius to a constant
CTlab = rgb2lab(CTrgb);
[th,~] = cart2pol(CTlab(:,2),CTlab(:,3));
[CTa CTb] = pol2cart(th,radius);
% put something relevant in the axes
% just to show that the alignment is correct
csview('lab'); % THIS IS MIMT
xlim([-150 150])
ylim([-150 150])
hold on;
% plot a dense scatter to make the hue ring
scatter(CTa,CTb,30,CTrgb,'filled');
Note that I used MIMT csview() for the example, but it's not at all necessary for your task. If that's something you want to use, for anything, let me know. The version that's current in MIMT is kind of janky garbage. I rewrote it last week but haven't uploaded it yet.
  7 Comments
DGM
DGM on 6 Mar 2022
No problem.
By the way, did you catch the late response I made on your other post about trying to draw slice boundaries?
If you want to stick with the way you're doing it, that's fine. I was just a bit overeager to share, since I don't know of anything that does what maxchroma() can do so succinctly.
Roger Breton
Roger Breton on 7 Mar 2022
For now, I think I'll experiment with your latest code, in a scatter3 form, along these lines :
% parameters
npoints = 1000;
radius = 100;
% get a cyclic rgb color map
CTrgb = hsv(npoints); % 1000 x 3 double
% project it into the desired space, set radius to a constant
CTlab = rgb2lab(CTrgb);
[th,~] = cart2pol(CTlab(:,2),CTlab(:,3));
[CTa CTb] = pol2cart(th,radius); % CTa et CTb = 1000 x 1 double
z = zeros(size(CTa));
scatter3(CTa,CTb,z, 30,CTrgb,'filled');
axis([-128 128 -128 128 0 100]);grid on;hold on;
I created a zeroes vector for the Z coordinate and this is what the above code gets me :
I think this is perfect. The only thing I'll have to come with next is a line radiating from the center representing the hue angle... I'll look into "slice boundaries"? I'll have to refresh my memory as to what I was looking for... But I'll report on the integration of this object in my existing 3D graph, which shouldn't be too hard. This is so rewarding and uses functions I had no idea existed.... I have no excuse not to learn Matlab better :( ...

Sign in to comment.

More Answers (5)

Image Analyst
Image Analyst on 3 Mar 2022
Perhaps you can adapt my attached demo.
  6 Comments
Roger Breton
Roger Breton on 4 Mar 2022
I scream "victory" too fast... There is not colormap support in viscircle :( I'll have to roll-up my sleeves and come up with something that could include some of these manual instructions to construct a cirle mathematically :
angles = linspace(0, 2*pi, 500);
radius = 20;
CenterX = 50;
CenterY = 40;
x = radius * cos(angles) + CenterX;
y = radius * sin(angles) + CenterY;
plot(x, y, 'LineWidth', 2);
Another "idea" I had in mind, after seing some of your code, was to create a series of circles, each with their own color but only visible through a series of mask? ...
Les Beckham
Les Beckham on 4 Mar 2022
@Image Analyst provided a comment here that shows what you can achieve using the surface command. I see no reason that this approach wouldn't at least get you close to what you want to do. Just define the x/y/z coordinates of your circle and make the color vary with the angle as you go around the circle.

Sign in to comment.


Les Beckham
Les Beckham on 4 Mar 2022
As I mentioned in my comment to @Image Analyst's answer, surface may be what you want.
I decided to experiment with it and came up with this based on his example.
See if it is close to what you want.
r = 50;
rho = linspace(0, 2*pi, 1920); % HDTV resolution.
x = cos(rho) * r;
y = sin(rho) * r;
z = zeros(size(x));
lineColor = rho(1:2:end); % This is the color, it varies with rho in this case.
lineColor = [lineColor flip(lineColor)];
% Plot the line with width 8 so we can see the colors well.
surface([x;x], [y;y], [z;z], [lineColor;lineColor],...
'FaceColor', 'no',...
'EdgeColor', 'interp',...
'LineWidth', 8);
grid on;
axis equal
view(16.5, 25)
  1 Comment
Roger Breton
Roger Breton on 5 Mar 2022
Edited: Roger Breton on 5 Mar 2022
Wow!!!!!!!!!!!!!!!!!! Thank you!!!!!!!!!!
Can't wait to try your code out!!!
One of the thing I albsolutely LOVE about Matlab is its "interactivity"!
Stepping through each line of your script, to see the role of each variable...
I owe you a beer :-)

Sign in to comment.


Image Analyst
Image Analyst on 4 Mar 2022
Edited: Image Analyst on 4 Mar 2022
You can make a colored circle by plotting markers:
numPoints = 1000;
angle = linspace(0, 360, numPoints);
x = sind(angle);
y = cosd(angle);
colors = hsv(numPoints);
for k = 1 : numPoints
plot(x(k), y(k), '.', 'MarkerSize', 20, 'Color', colors(k,:));
hold on;
end
grid on;
xlabel('x');
ylabel('y');
axis equal
  3 Comments
Roger Breton
Roger Breton on 5 Mar 2022
After experimenting with your last code, compared with Les Beckam code, I think I'll try my luck with your code... I won't be using the HSV() function to come up with the RGB colors to plot but some "function", as my intuition tells me, derived from the Hue angle and Chroma, convertted to Lab and sRGB... This is fun :-)
Image Analyst
Image Analyst on 5 Mar 2022
Yes, essentially colors is an N b y 2 array (colormap) and you can put whatever color you want into each row to get the colors to be in the proper order.

Sign in to comment.


Roger Breton
Roger Breton on 7 Mar 2022
I integrated the function into my script and it works like a charm. I may reduce the number of points from 1000 to 500 to speed up performance but otherwise, this is perfect. Now I just have to figure how to control that "blue" line, which should stand for the selected color hue angle :
  3 Comments
Roger Breton
Roger Breton on 7 Mar 2022
I just found out that my custom data tip function also works on the Lch color wheel points (which I reduced down to 500)!!! :
This is so satisfying.
I'll try your code for drawling the line but I'm not sure coloring the line with the Hue and Chroma and Lightness of the selected point is "best"? I'll give it a try but I'm afraid of situations like Yellows which a "yellow line" will be difficult to see against a "white" background. I'd have to invert the background color, perhaps? But thank you so very mych for the code, whicih I'm going to study next....
DGM
DGM on 9 Mar 2022
For what it's worth, the hue ring part can probably be reduced to a literal CT and point list if you want simplicity and speed. Attached is a .mat file containing a uniform 200-point ring. My assumption about how much the interpolation would cost for a uniform ring was wrong. The reduction in point count is significant enough that that it's actually faster. Using the precalculated result is faster yet, and it's concise:
S = load('huering.mat');
% put something relevant in the axes
% just to show that the alignment is correct
csview('lab');
xlim([-150 150])
ylim([-150 150])
hold on;
% plot a scatter to make the hue ring
scatter(S.CTa,S.CTb,30,S.newCTrgb,'filled'); hold on
That makes for a relatively solid ring with only 200 points.
This is how I calculated the points and new CT:
% parameters
npoints = 200;
radius = 100;
% get a cyclic rgb color map
CTrgb = hsv(npoints);
CTlch = rgb2lch(ct2im(CTrgb),'lab');
H = rad2deg(unwrap(deg2rad(CTlch(:,:,3))));
newH = linspace(H(1),H(end),npoints).';
newCTrgb = interp1(H,CTrgb,newH);
% get A,B coordinates
CTa = radius*cosd(newH);
CTb = radius*sind(newH);
%save('huering.mat','newCTrgb','CTa','CTb');
I cheated and used MIMT rgb2lch(), but that can be done with rgb2lab() and polar conversions.

Sign in to comment.


Roger Breton
Roger Breton on 9 Mar 2022
A final note. This project is far from over. It's getting all kinds of suggestions and usecases (by me).
I enclose the code, if that could help someone. Here's a screen capture of the current interface:
There's a ton of work, still, needed to be done. But it starts to take shape. You see, on the right, is a page frome the Munsell Book of Colors. This is the hue slice = 10P, a shade of purple. When I click the mouse on the chart, it shows the CIE Lab color location iin 3D on the left. With this kind of image, since there aren't too many "data points", representing discrete colors, it's easy to recognize the 3D structure underlying the Munsell chips. I think that's going to be a good eye opener for students coming into my humble Photoshop classes. Forgot to say, for those of you who are interested, I created an extra graphic function to show the location and orientation of the "Hue angle". Once the user clicks on the "plot2D" button, after clicking a data point with the data cursor tool, there is a black dotted line that appears at the bottom, in the correct orientation of the selected hue color (sorry, I'm always tempted to capitalize the H in the word hue). At first, its length was equal to its a*/b* coordinates but that was not ideal, so I switched to a fixed value. First, same as the Lch circle radius, 100, but then I thought it would be best to expand it, to 128, the maximum a* and b* values I use (8 bit). I think it's doing a terrific job of helping to visualize a color.

Categories

Find more on Data Distribution Plots in Help Center and File Exchange

Products


Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!