Control the saturation of an image

5 views (last 30 days)
Philipp
Philipp on 29 Apr 2013
Edited: DGM on 8 Nov 2022
Dear people,
perhaps a very basic question, but I am new to colormaps.
I have two matrices A and B, and I want to depict both in one image. How can I achieve that matrix A controls the hue of the image and matrix B the saturation?
Thank you,
Philipp

Answers (1)

DGM
DGM on 8 Nov 2022
Edited: DGM on 8 Nov 2022
Let's assume that the goal is as follows. User has three RGB images. From two of the images, the hue and saturation content (respectively) are to be extracted and applied to the third image.
So long as the images share the same geometry, this is fairly straightforward. Let's say we have the following three images
The base image
The H source
The S source
% read the images
inpict = imread('peppers.png'); % base image
Hpict = imread('hpict.png'); % source for H
Spict = imread('spict.png'); % source for S
% extract the relevant channels from each image
[Hnew,~,~] = imsplit(rgb2hsv(Hpict));
[~,Snew,~] = imsplit(rgb2hsv(Spict));
[~,~,Vold] = imsplit(rgb2hsv(inpict));
% concatenate and convert to RGB
outpict = cat(3,Hnew,Snew,Vold);
outpict = hsv2rgb(outpict);
imshow(outpict)
While that's easy enough, the results are pretty terrible. That yellow pepper is completely blown out. That should be expected. HSV is probably the worst model to use for color blending like this.
As bad as it is, it could be at least easier. Basic image blending tools like MIMT imblend() can typically do color component transfer blends. While most won't support HSV in the named "hue" or "saturation" modes, imblend() does offer the capability. These two lines will replicate the output above.
% read the images
inpict = imread('peppers.png'); % base image
Hpict = imread('hpict.png'); % source for H
Spict = imread('spict.png'); % source for S
% use MIMT imblend()
outpict = imblend(Spict,inpict,1,'transfer s_hsv>s_hsv');
outpict = imblend(Hpict,outpict,1,'transfer h_hsv>h_hsv');
imshow(outpict)
Instead of using HSV, you could do the channel swap in something with a symmetric saturation space. HSL is what's used by GIMP, and it works here as well.
% use HSL instead of HSV
outpict = imblend(Spict,inpict,1,'transfer s_hsl>s_hsl');
outpict = imblend(Hpict,outpict,1,'transfer h_hsl>h_hsl');
While HSL is a far better option for this than HSV, it's still pretty poor at preserving local brightness. A common trick in old software is to do some sort of luma correction after large HS alterations.
% use luma-corrected HSL
outpict = imblend(Spict,inpict,1,'transfer s_hsl>s_hsl');
outpict = imblend(Hpict,outpict,1,'transfer h_hsl>h_hsl');
outpict = imblend(inpict,outpict,1,'luma');
The named 'hue' and 'saturation' modes in imblend() actually do an HC swap in LCHab, with constraint on C to keep colors in-gamut. This is the default behavior for the named modes because it tends to do the best job.
% use H and C in LCHab
outpict = imblend(Spict,inpict,1,'saturation');
outpict = imblend(Hpict,outpict,1,'hue');
That said, a constrained HC swap in LCH is a lot more complicated and expensive than doing a luma-corrected HS swap in HSL. That's why HSL+Y workarounds may be an attractive compromise.
While a luma-corrected HS swap is simple and could easily be done without imblend(), there isn't much point in posting an example. MATLAB/IPT does not have HSL conversion tools, so any example I gave would still depend on third party tools such as MIMT. If one already has MIMT, I don't see the point in avoiding the image blender.
% HSL+Y channel swapping without imblend()
% read the images
inpict = imread('peppers.png'); % base image
Hpict = imread('hpict.png'); % source for H
Spict = imread('spict.png'); % source for S
rec = '601'; % specifies luma constants
A = gettfm('ypbpr',rec); % get forward/inv xform matrices
Ai = gettfm('ypbpr_inv',rec);
Y = imappmat(imcast(inpict,'double'),A(1,:,:)); % save Y
[Hnew,~,~] = splitchans(rgb2hsl(Hpict)); % split and combine as before
[~,Snew,~] = splitchans(rgb2hsl(Spict));
[~,~,Lold] = splitchans(rgb2hsl(inpict));
outpict = cat(3,Hnew,Snew,Lold);
outpict = hsl2rgb(outpict);
Rpbpr = imappmat(outpict,A(2:3,:,:)); % extract new PbPr, discard new Y
outpict = imappmat(cat(3,Y,Rpbpr),Ai); % combine new PbPr with old Y, convert
imshow(outpict)
... but I'll post an example anyway. Again, this still depends on MIMT for most things.
Alternatively, suppose that the original question were about composing an image from three single-channel images, or from two single channel images and a base RGB image. Given the first example, it should be fairly simple to adapt to these possible cases.
Lastly, consider that the images are not necessarily the same size and the object content of each is unimportant. Perhaps the goal is simply to recolor the base image based on the colors in the first two, but not based on the object content in either. If that's the case, consider this answer.

Categories

Find more on Convert Image Type in Help Center and File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!