How to set the hue and saturation value in hsv color model.
12 views (last 30 days)
Show older comments
i have a color image ,i need to convert into hsv image.After converting i need to set the hue value between (10 to 40) and saturation value between(100–255). How to achieve this in matlab2016 version
3 Comments
Answers (1)
DGM
on 19 Apr 2022
I doubt this question needs to be solved anymore, but it brings up an issue that's easy to miss.
In general, when someone asks "how to I constrain image values to a given range, there are a couple obvious answers. You can either truncate the values, or you can rescale them to fit. What you choose depends on your goals. Rescaling is typically going to produce results which have better retention of local contrast and are less visually objectionable. So let's try doing both.
First, let's truncate H and S.
A = imread('peppers.png');
% convert and split
Ahsv = rgb2hsv(A);
[H S V] = imsplit(Ahsv);
% truncate S
Snew = imclamp(S,[100 255]/255);
figure
subplot(2,1,1); imhist(S) % show histogram before
subplot(2,1,2); imhist(Snew) % show histogram after
% blindly truncate H
Hnew = imclamp(H,[10 40]/255);
figure
subplot(2,1,1); imhist(H) % show histogram before
subplot(2,1,2); imhist(Hnew) % show histogram after
% reassemble image
B = hsv2rgb(cat(3,Hnew,Snew,V));
% show result
figure
imshow(B)
Then let's rescale H and S.
A = imread('peppers.png');
% convert and split
Ahsv = rgb2hsv(A);
[H S V] = imsplit(Ahsv);
% rescale S
Snew = imadjust(S,[0 1],[100 255]/255);
figure
subplot(2,1,1); imhist(S) % show histogram before
subplot(2,1,2); imhist(Snew) % show histogram after
% blindly rescale H
Hnew = imadjust(H,[0 1],[10 40]/255);
figure
subplot(2,1,1); imhist(H) % show histogram before
subplot(2,1,2); imhist(Hnew) % show histogram after
% reassemble image
B = hsv2rgb(cat(3,Hnew,Snew,V));
% show result
figure
imshow(B)
Well, those both look like garbage. Rescaling or truncating S or V is fairly straightforward, but H is a circular continuum. H = 10 is closer to H = 350 than it is to H = 40. When you move the endpoints of the transfer curve away from [0 1], you're splitting what used to be a continuous space and potentially moving color points away from their neighbors.
In this example, the hue distribution is largely centered around red -- around H = 0. In this particular case, the hue distribution has clear extents. If we recognize this, we can do something strategic:
A = imread('peppers.png');
% convert and split
Ahsv = rgb2hsv(A);
[H S V] = imsplit(Ahsv);
% rescale S
Snew = imadjust(S,[0 1],[100 255]/255);
figure
subplot(2,1,1); imhist(S) % show histogram before
subplot(2,1,2); imhist(Snew) % show histogram after
% rotate H prior to rescaling
Hnew = mod(H+0.5,1);
Hnew = imadjust(Hnew,[0 1],[10 40]/255);
figure
subplot(2,1,1); imhist(H) % show histogram before
subplot(2,1,2); imhist(Hnew) % show histogram after
% reassemble image
B = hsv2rgb(cat(3,Hnew,Snew,V));
% show result
figure
imshow(B)
By rotating H prior to rescaling, the hue distribution doesn't get split and the image remains smooth. Of course, one can easily imagine a colorful image where there is no good place to split the histogram, so this isn't a general solution. In fact, it's such an underspecified problem that one has to question the applicability of any solution.
There are certainly trivial ways to accomplish the goals for any image. Say we simply discard the original H content:
A = imread('peppers.png');
% convert and split
Ahsv = rgb2hsv(A);
[H S V] = imsplit(Ahsv);
% rescale S
Snew = imadjust(S,[0 1],[100 255]/255);
% replace H with an arbitrary field within the specified interval
Hnew = repmat(linspace(10/255,40/255,size(H,1)).',[1 size(H,2)]);
% reassemble image
B = hsv2rgb(cat(3,Hnew,Snew,V));
% show result
figure
imshow(B)
A = imread('peppers.png');
% convert and split
Ahsv = rgb2hsv(A);
[H S V] = imsplit(Ahsv);
% rescale S
Snew = imadjust(S,[0 1],[100 255]/255);
% replace H with a scaled copy of V
Hnew = 10/255 + 30/255*V;
% reassemble image
B = hsv2rgb(cat(3,Hnew,Snew,V));
% show result
figure
imshow(B)
You'll have to decide what the actual requirements are.
2 Comments
Imran Riaz
on 20 Jul 2022
I have similiar problem, I want to remove the background of finger images, but brightness and contrast level of every person have different values, so how I can adjust it? Images are attached herewith.
DGM
on 20 Jul 2022
That really isn't related to hue manipulation and continuity. That's a segmentation problem that stems from a lack of demonstrable constraints. It might be one thing to extract an apple from one image using static thresholds. It might even work for a number of similar images, but if someone asks "I have this handful of images. How can I pick fixed thresholds that will let me isolate any apple from any image", the answer is that there's no reason to believe that such things are even possible.
The problem might be solved for two images:
A = imread('012-07-L.jpg');
B = imread('023-07-L.jpg');
% just cram both samples into one image
% to demonstrate that the segmentation works on the union of images
AB = imresize([A;B],0.5);
ABhsv = rgb2hsv(AB);
% HSV thresholds
th = [0.70 0.12;
0.00 1.00;
0.00 0.85];
% basic color-based mask generation
th = permute(th,[3 2 1]);
mask = all(ABhsv(:,:,1) >= th(1,1,1) | ABhsv(:,:,1) <= th(1,2,1),3);
mask = all(ABhsv(:,:,2:3) >= th(1,1,2:3) & ABhsv(:,:,2:3) <= th(1,2,2:3),3) & mask;
% remove speckles
minspecksize = 50;
mask = bwareaopen(mask,minspecksize);
mask = ~bwareaopen(~mask,minspecksize);
% show combined mask
imshow(mask)
... but without knowing the full scope of the lighting and tone variations across all the images, there's no way to know if this will work for any images in the dataset other than these two. It's probably good for quite a few, but that's not something that can be known from here.
If static thresholds aren't sufficiently robust for this sort of thing, what is? I don't know. Despite the fact that I gave an example, this really belongs in a new question.
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!