Create (plot) sRGB gamut, using the boundary function?

6 views (last 30 days)
I would like to show a gamut outline when the student checks off the sRGB checkbox in the figure. On the left, is the result of a the sRGB scatter at L* = 50 slice, while on the right is with sRGB scatter unchecked, letting the "image" scatter points show through :
I would like to show an outline of the sRGB gamut when the sRGB checkbox is unchecked but I don't see the necessary matrix operation that would do that? All I can see, intuitively, for the moment, is that using the boundary function would create such a plot. I attached a copy of my script. (I have not attached any of the images...) I sense the new statements I require would be around this code :
% these only need to be set once
persistent aa bb Axe_a_b
if isempty(aa)
Axe_a_b = linspace(-maxab, maxab, numstepsab);
[aa bb] = meshgrid(Axe_a_b);
aa = aa(:);
bb = bb(:);
ll = sliderval*ones(numstepsab^2,1); % 4225 double
% build colordata
colorListAB = lab2rgb([ll aa bb]);
isoog = any(colorListAB > 1 | colorListAB < 0,2);
colorListAB(isoog,:) = 0.5; % Ramène les valeurs à gris
Somehow, I think I required to create a new ColorList that would only include, say, the entries where the values are equal to 0.5, since these values represent the out of gamut colors.
Any help is appreciated.
Please forgive all the globals and newbie code...

Accepted Answer

Roger Breton
Roger Breton on 11 Feb 2022
Here's my code :
colorListAB(isoog,:) = 0.5; % Ramène les valeurs à gris
row = find( colorListAB(:,1)~= 0.5 );
AA = colorListAB(row,:) % Build a new matrix A that satisfies the condition of 1's and 3's
InGamut = rgb2lab(AA);
xlim([-128 128])
ylim([-128 128])
hold on;
x_bound = InGamut(:,2);
y_bound = InGamut(:,3);
k = boundary(x_bound,y_bound);
hold on;
It took me a while to understand the logic behind 'selecting' data out of a matrix? It may not be the most elegant solution but it works :
We'll see how this applies to the rest of the script.

More Answers (2)

Image Analyst
Image Analyst on 11 Feb 2022
How about if you use convhull()?
Image Analyst
Image Analyst on 11 Feb 2022
Well there is convhull() for 2-D point sets, and convhulln() for higher dimensional point sets. You might also look at activecontour() for boundaries that can be tuned for how closely they hug/follow the outer perimeter of points. Demo attached.
You can also look at the "restricted convex hull to get a boundary that is not completely convex but has some "bays" in it.

Sign in to comment.

DGM on 12 Feb 2022
Edited: DGM on 12 Feb 2022
This uses MIMT tools to do the job.
MIMT maxchroma() works in LCHab (or other polar models) to find the envelope of maximum chroma for a given L and H.
N = 1000; % number of points
Ll = 50; % L level
% find boundary curve
L = Ll.*ones(1,N);
H = linspace(0,360,N);
C = maxchroma('lab','l',L,'h',H);
[a b] = pol2cart(deg2rad(H),C);
plot(a,b); hold on
xlim([-128 128])
ylim([-128 128])
Alternatively (or in combination with plot(), you can create a colored pseudoline using a dense scatter() plot. This might require much more plot points due the fact that the gamut boundaries are tangential to lines of constant hue in some places.
% plot as a colored pseudoline using scatter
CT = lch2rgb(cat(3,L,C,H),'lab');
CT = permute(CT,[2 3 1]);
Regarding that last statement:
This is the boundary chroma map for L = 97.14, H = [90 120]
In LAB, the gamut boundaries pass through tangency with lines of constant hue (vertical lines in the above image). This isn't something that happens in LUV.
This means that for certain L and H, the actual gamut boundary is somewhere inside the envelope of maximum chroma. Since maxchroma() finds the chroma envelope in this polar space, it cannot represent these concavities. All it returns is the envelope.
Luckily for you, this probably won't be too noticeable. LAB only has this behavior near the yellow corner (mostly on the R=1 face), and the concavity is small.
If you really want to tighten it up, you can, but it would be more expensive. Consider the example doing both ways
N = 1000; % number of points
Ll = 97.14; % L level
% find boundary curve as before
L = Ll.*ones(1,N);
H = linspace(0,360,N);
C = maxchroma('lab','l',L,'h',H);
[a b] = pol2cart(deg2rad(H),C);
plot(a,b,'k--'); hold on
% exploit truncation in RGB to tighten the boundary
% skip gamma correction for speed (it's irrelevant at the boundary)
A = lch2rgb(cat(3,L,C,H),'lab','truncatergb','nogc');
A = rgb2lch(A,'lab','nogc');
[L C H] = imsplit(A);
[a b] = pol2cart(deg2rad(H),C);
plot(a,b,'k'); hold on
xlim([-50 50]) % plotted over a smaller domain for clarity
ylim([-20 90])
You could reduce the impact of this extra conversion cycle by conditionally applying it only for cases where L>85.

Community Treasure Hunt

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

Start Hunting!