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

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".

 채택된 답변

DGM
DGM 2022년 3월 5일
편집: DGM 2022년 3월 5일
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

Wow! Again, you are 1000 steps ahead of me..... Let me digest your code........
Obviously, I can't get to the final results because of MIMT csview() ....
Have to think about what to use instead....
As I mentioned, csview() was just there to provide the gamut shape for the sake of the demonstration. It can simply be omitted if all you want is the ring.
If csview is something that you find yourself wanting to use, I have updated MIMT and the new copy should be up here:
OK... If I comment out the "csview" line, I get a superlative CIE Lab circle...
Wow! Thank you so much!
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.
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 :( ...

댓글을 달려면 로그인하십시오.

추가 답변 (5개)

Perhaps you can adapt my attached demo.

댓글 수: 6

Boy! I'm willing to try anything, dear friend -- thank you so much for your generousity :-)
I added the following statement viscircles([0 0],50) after creating the axes :
handleScatter3D = scatter3(LabIMG(2,:),LabIMG(3,:),LabIMG(1,:),Diam,rawRGB,'fill', 'MarkerEdgeColor', [0.5,0.5,0.5], 'Linewidth', 0.5);
xlabel('b* (X)'),ylabel('a* (Y)'),zlabel('L* (Z)');
title('CIE-L*a*b* coordinates'); % Propriété des Axes
axis([-128 128 -128 128 0 100]);grid on;hold on;
viscircles([0 0],50) <<<<<<<<<<<<<<<<<<<<--------------------------
And got this, which is an incredible start :
Boy! Thank you for all the scripts you just attached!!!!!!
I'll probably have a bitch of a time to color the outline of the circle with a colormap? ... We'll see. Usually, things are never as simple I would want them in Matltab :(
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? ...
@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.

댓글을 달려면 로그인하십시오.

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

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 :-)

댓글을 달려면 로그인하십시오.

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

Wow!!!!!!!!!!!!!! Thank you SO much!!!!!!!!!!!!!!
You are spoling me!!!!!!!!!!!
I was going to experiment with a loop, as I thought it would be the only way to control the color at each "point' around the circle, "cicrle" being constructed out of a number of joined line segments.
You used HSV to calculate which colors to put at which angles. My goal is to use Lab "sRGB" colors possibly out of Lch values... Boy! I have to invert Lch to Lab... Never done that... More math! I never was a math buff in school -- I flunk introductory Linear Algebra three times...
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 :-)
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.

댓글을 달려면 로그인하십시오.

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

I guess it depends on what you want the marker line to represent. If it's just to represent the hue and have some fixed radius, then that's easy enough:
hmarkhue = 135;
hmarkchr = 150;
plot([0 hmarkchr*cosd(hmarkhue)],[0 hmarkchr*sind(hmarkhue)],'linewidth',2)
If you want it to be a projection of the selected point's position vector (representing both hue and chroma), and your working in rectangular coordinates, then it'd be simpler to just plot the line based on the a,b values of the point instead of dealing with polar coordinates.
You can try thinning out the points in the hue ring. They get pretty sparse near cyan due to the distortion. I could probably come up with a way to plot them at a uniform density (thereby minimizing the number of points required), but it would probably involve an extra interpolation step or so. It would use fewer points, but it's be more expensive to calculate. Depends whether the issue is the cost of calculation or the cost of having more objects in the axes.
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....
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.

댓글을 달려면 로그인하십시오.

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.

댓글 수: 2

Is this something you might think about releasing on the File Exchange when it's all done?

댓글을 달려면 로그인하십시오.

카테고리

도움말 센터File Exchange에서 Blue에 대해 자세히 알아보기

제품

릴리스

R2020b

질문:

2022년 3월 3일

댓글:

DGM
2022년 3월 9일

Community Treasure Hunt

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

Start Hunting!

Translated by