applying thresholds simultaneously in SimpleColo​rDetection​ByHue()

I'm trying to use this program to detect not one but three different colors (red green blue) at the same time, applying three different thresholds. Is there a way? Try to explain each little step because I haven't used Matlab for a while and I'm a bit rusty. Thank you all!

 Accepted Answer

Yes, basically just do each color one at a time and get a mask for each one, then OR them together.
% Set hsv thresholds for color1
maskColor1 = ........ % Create mask based on those thresholds.
% Set hsv thresholds for color2
maskColor2 = ........
% Set hsv thresholds for color3
maskColor3 = ........
% Get the mask for all 3
allThreeColorsMask = maskColor1 | maskColor2 | maskColor3;

17 Comments

Thanks Image Analyst, that helped me a lot and I managed to solve this problem! I have another problem though: setting the thresholds. It seems that no matter how I set them, I cannot get a proper black/dark colour in the areas where there's no green/red/blue. Original and masked pictures look the same. Any tips? I can attach the pictures so you can get a better idea. Thank you!
Try the Color Thresholder app on the Apps tab to figure out what thresholds to use.
Thanks. I used that app and it worked really good. Kinda though, since if I select only the green and blue part it works and gives me good results, but if I select also the red one (or only the red one) it gives me wrong results (red part is basically pitch black). I did the 'OR them together' mask and I also looked at your suggestion in the code saying I should create two hue masks for red to catch every kind of red, but still doesn't work. I'm almost certain I did everything I could. I paste here the script of those passages:
Thresholds
%%%%%%
%Red
hueThresholdLowR1 = 0.8;
hueThresholdHighR1 = 1;
hueThresholdLowR2 = 0;
hueThresholdHighR2 = 0.1;
saturationThresholdLowR = 0.6;
saturationThresholdHighR = 1;
valueThresholdLowR = 0.55;
valueThresholdHighR = 1;
Hue mask for red
%red
hueMaskR1 = (hImage >= hueThresholdLowR1) & (hImage <= hueThresholdHighR1);
hueMaskR2 = (hImage >= hueThresholdLowR2) & (hImage <= hueThresholdHighR2);
hueMaskR = hueMaskR1 & hueMaskR2;
saturationMaskR = (sImage >= saturationThresholdLowR) & (sImage <= saturationThresholdHighR);
valueMaskR = (vImage >= valueThresholdLowR) & (vImage <= valueThresholdHighR);
(then regular masks for the other two colors) and combine them
%%%%%%%%%%%%%
%combine the three masks for the three colors in a unique mask
hueMask = hueMaskR | hueMaskG | hueMaskB;
saturationMask = saturationMaskR | saturationMaskG | saturationMaskB;
valueMask = valueMaskR | valueMaskG | valueMaskB;
Let me know what I'm doing wrong Cheers
You anded the red masks when you should have ORed:
hueMaskR = hueMaskR1 | hueMaskR2;
Attached is fixed code.
Thank you! Is it possible that the 3 masks are conflicting with each other? I tried Color threshold app, the threshold function you posted and some other approaches on the web but I can't seem to get good results. When apply the mask composed by the three different color masks combined I never fully get the mask I want. Is there a stable way or the only way is to manually play with the thresholds values until something goes right? I've been trying for hours.
To add more to my question. My aim is to find porosity of a cropped area. porosity Index is between 0 and 1. In the case that I mentioned and you helped me to correct, even if I apply the correct thresholds the index should be around 0.4 but it's stuck at 0.1 or even negative!
I'm not sure what you're asking. You get each mask, for each color, one at a time. Red is a little trickier than the others because it shows up both for hue > 0.9 and for hues < 0.1. I suppose there are some colors that could be in more than one mask, or not in any mask. Are you asking about those pixels? It depends on what you're doing. If you just want to find porosity/opacity, then maybe you should just ignore hue and threshold on either the value channel or the saturation channel.
Yes I just need a method that works for evaluating porosity. I don't really care about which color occupies which pixel. I think I'll try to threshold only S or V as you suggested and see how it goes! Thanks again.
Did what you suggested but still poor results. Porosity should be ~0.4 and is ~0.8 instead. I'm thinking maybe HSV is not the right 'space' to do this since the colored pic loses definition?
What do you consider the "porous" areas? The darkly colored, black areas?
yes exactly those! I still think there must be a kinda easy way but the results are not there yet.
Why not just threshold the V channel?
darkAreas = vChannel < someBrightnessValue;
porosity = sum(darkAreas(:))/numel(darkAreas);
I haven't heard back from you. So, did that work or not???
Yes it Worked! Thanks man! I think there were some value areas (of shade) that escaped the color mask. I still used the color mask to get a good graphic representation and then 'leveled' the porosity index to a more reasonable one adding a value threshold. So far it's been stable :)
OK, great. Can you then "Accept this answer"? Thanks.
Done! One more question. What about if I want to evaluate the porosity in 4 areas of the cropped image? Would it be something like:
%
hsvImage = rgb2hsv(rgbImage);
[r, c, p] = size(hsvImage);
DarkAreas1 = vImage(1:r,1:c/4,:);
Porosity1 = sum(darkAreas1(:))/numel(darkAreas);
same thing for the other three areas and then mean for the total porosity? (it's to display the heterogeneity of the index from top to bottom of the image). Then I wanted to load another image after the elements have been stressed to evaluate the same index and a global one for comparison. The important thing is that the cropped area has to be the same in coordinates and width/height (pic position will be the same since it's same camera and same position of shooting). It has something to do with 'rect' command but I'm not sure what. Thank you. Please tell me if I should create another question for this. :)
Not sure what you want, but what you are doing is taking the leftmost quarter strip of the image, and getting the mean all the gray levels in that vertical strip. The last two lines could be done like this:
Porosity1 = mean2(vImage(1:r,1:c/4,:));
Of course you need to define vImage. Did you mean hsvImage? Or did you mean (but left out)
vImage = hsvImage(:, :, 1); % Extract value channel.
If you meant that, then you can leave off the final colon:
Porosity1 = mean2(vImage(1:r,1:c/4));
If you want a fixed number of columns, instead of 1/4 the width of the image, then just specify it. For example, use 100 instead of c/4. It does not need to involve rect() unless you want the user to be able to adjust the location of the box interactively over the image.

Sign in to comment.

More Answers (1)

how to change input image as real time web cam in the laptop on matlab coading

Categories

Find more on Image Processing and Computer Vision in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!