Clear Filters
Clear Filters

Need help with Tooltip display?

6 views (last 30 days)
Roger Breton
Roger Breton on 29 Feb 2024
Commented: Roger Breton on 1 Mar 2024
I have a script that plots CIE Lab values in 3D:
Works great. But as you can see, the tooltip displays the XYZ value.
Instead, I would like it to display the "name of the color".
I asked chatGPT and it suggested the following code:
dcm = datacursormode(gcf);
set(dcm, 'UpdateFcn', @customDataCursor);
function txt = customDataCursor(~, event_obj)
pos = event_obj.Position;
color_name = getColorNameFromRGB(pos, colors);
txt = {['Color: ' color_name]};
end
function color_name = getColorNameFromRGB(rgb, color_struct)
% Implement logic to find the closest color name based on RGB value
% (e.g., Euclidean distance or other methods).
% Return the corresponding color name.
% For simplicity, you can use a lookup table or hard-coded mapping.
% Example:
color_name = 'PamplemousseRose'; % Replace with actual logic
end
I'm kind of lost. Upon initialization of my script, I use the following statements:
T = readtable('SICO Accents de couleur (2023 09 25).xlsx');
colorNames = T(:, 1); % Extract the color names (column 1)
labValues = T(:, 2:4); % Extract the CIE Lab values (columns 2 to 4)
Can I use a command such as "find"?

Accepted Answer

Voss
Voss on 29 Feb 2024
Here is a script you can run, along with an xlsx file containing random colors and names.
You can run it as-is, and you can also substitute your own xlsx file and see how it does with that.
% a scatter plot
figure
scatter3(200*rand(10,1)-100,200*rand(10,1)-100,100*rand(10,1),[],rand(10,1),'filled')
xlabel('b* (X)')
ylabel('a* (Y)')
zlabel('L* (Z)')
% color table
colors = readtable('colors.xlsx');
% data cursor with custom update function
dcm = datacursormode(gcf);
set(dcm, 'UpdateFcn', {@customDataCursor,colors});
% data cursor update function
function txt = customDataCursor(~, event_obj, colors)
pos = event_obj.Position;
color_name = getColorNameFromLAB(pos, colors);
txt = {['Color: ' color_name{1}]};
end
% helper function
function color_name = getColorNameFromLAB(pos, colors)
% pos is in (X,Y,Z) = (b,a,L) order and colors are in L,a,b order (I assume),
% so use colors{:,[4 3 2]}, i.e., b,a,L order to compare with pos
d2 = sum((pos-colors{:,[4 3 2]}).^2,2); % squared Euclidean distance from pos to colors
[~,idx] = min(d2); % index of minimum squared distance
color_name = colors{idx,1}; % color name at that index
end
  4 Comments
Voss
Voss on 29 Feb 2024
You're welcome! Looks good. The best code is code that: (1) works, and (2) makes sense to the programmer.
Roger Breton
Roger Breton on 1 Mar 2024
I managed to push the enveloppe a little and also display the DeltaE76 value.
See attached video (don't mind the French comments):
% Create a handle to the customDataCursor function
dcm = datacursormode(gcf);
set(dcm, 'UpdateFcn', @(src, event_obj) customDataCursor(src, event_obj, CIE_L, CIE_a, CIE_b, NomsCouleur));
function txt = customDataCursor(~, event_obj, CIE_L, CIE_a, CIE_b, NomsCouleur)
pos = event_obj.Position; % pos = 76 6 50 / 1x3 double
target_a = pos(1); % X 76
target_b = pos(2); % Y 6
target_L = pos(3); % Z 50
target_Lab = [target_L, target_a, target_b];
RGB = lab2rgb(target_Lab, 'ColorSpace','srgb', 'WhitePoint','d50');
% Check if any value is below zero
isBelowZero = RGB < 0;
isGreaterThanOne = RGB > 1;
Asterix='';
dE76=0;
% Display the result
if any(isBelowZero) || any(isGreaterThanOne)
Asterix = "*";
% Normalize RGB values to the range [0, 1]
NormRGB = max(0, min(1, RGB));
LabOut = rgb2lab(NormRGB, 'ColorSpace','srgb', 'WhitePoint','d50');
dE76 = sqrt((LabOut(1) - target_L)^2 + (LabOut(2) - target_a)^2 + (LabOut(3) - target_b)^2);
end
% Calculate Euclidean distances
distances = sqrt((CIE_L - target_L).^2 + (CIE_a - target_a).^2 + (CIE_b - target_b).^2);
[~, minIndex] = min(distances);
colorName = NomsCouleur(minIndex);
Couleur = char(colorName);
% Create a formatted string with the target L, a, and b values
% formattedCouleur = sprintf('%s (L=%.2f, a=%.2f, b=%.2f)', Couleur, target_L, target_a, target_b);
formattedCouleur = sprintf('%s (%d %d %d) %.2f', Couleur, target_L, target_a, target_b, dE76);
txt = {formattedCouleur};
end

Sign in to comment.

More Answers (0)

Products


Release

R2023a

Community Treasure Hunt

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

Start Hunting!