I am trying to write an algorithm for detection of the color green. The thing is that if I try detecting the shade of a pixel in a picture, there are more than a million different shades possible. How do I sift thourgh all these different shades and detect which ones are green ? Does anyone know of a simple way to do it or of any prevelant algorithms that does it for you ?
Kheun
August 18th, 2004, 09:58 PM
Assuming that your picture uses some form of RGB format to store the color for per pixel, you can distinguish if the color of a pixel is green if both red and blue colors are zero.
yiannakop
August 19th, 2004, 09:19 AM
One of the most popular methods used for this puprose is using the vector distance. I've used this in the past for detecting colors and it works fine. Here is a brief explanation:
Let's say you are searching for "green" pixels. Pure green exists when the values of the pixels are:
R = 0
G = 255
B = 0
Though, when searching for green you may want to have a "tolerance" meaning that you don't only search for pure green, but also for some other green-like combinations. Suppose that each pixel is a vector:
pixel = [R G B]
Also, the color combination you are looking for is another vector:
green = [0 255 0] (reference color)
The eucledian distance between those 2 vectors is:
D = sqrt((R-0)^2 + (G-255)^2 + (B-0)^2)
(in the place of 0 and 255 you can place whatever you want, according on the color combination you are looking for...)
So the algorithm goes:
for each pixel
{
1. compute the distance between that pixel and the reference color (D)
2. if D<Threshold
then
current pixel is accepted
else
current pixel is NOT accepted
}
PS1: "Threshold" is a constant value and has to bee set manually according on the "tolerance" you want to give to your algorithm (a high value of Threshold means that also less "clear" green pixels will be considered as green, whereas a lower value of Threshold will make the algorithm quite "strict").
PS2: Threshold can also be computed using addaptive algorithms but this is quite difficult
PS3: I've tested this simple algorithm using Matlab and it works fine, so if interested tell me to send you the code.
Hope this helped u. :wave:
yiannakop
August 19th, 2004, 09:26 AM
Also, you could try image segmentation technuiqes like:
- fuzzy logic
- k - means vector quantization
RoboTact
August 28th, 2004, 03:31 PM
I think you should give more tolerance to the brightness. To do so, norm the color vectors by 1 and then distance is distance between the resulting vectors+some cooff*difference in length.
yiannakop
August 30th, 2004, 10:17 AM
Nice idea RoboTact. Though, that depends on what the seach is done for. Maybe the user doesn't want to give tolerance to brightness. But if he does, then you are right, that by normalizing the RGB coefficients he achieves that.
Another way to do this is to execute histogram equalisation in each coefficient (R,G,B), or even better to transform the RGB matrix to HSI and perform histogram equalisation to the I coefficient only.
wsmmi6674
March 30th, 2005, 12:18 PM
Assuming you receive pixel values in RGB form, another option is to convert the color to HSV (Hue - Saturation - Value). Pure green has (I believe) a hue value of 192.
This would make it easier to weight saturation and light levels differently than hue.
--
Scott
barrensoul
March 31st, 2005, 01:28 AM
with a screen that is 32 bit you use this (this is how I get colours from a direct draw surface)
long colour = (*(reinterpret_cast<long*>(ddsd.lpSurface)+(Y*Xres+X)))&0x00FF00
&0x00FF00 is a bit mask that will extract the green value so all you need to do is this
if(colour) //if true then there is some green in the pixel
there ya go :) be carefull with 16 bit numbers as some systems consider 16 bit to be 15 ;)
(ddsd.lpSurface is a void pointer to the beginning of the screens memory address, which is why it needs to be reinterpreted)
oh and in a 24bit BMP (just RGB no alpha) you have 16,777,216 different colours ;)
yiannakop
April 8th, 2005, 10:38 AM
Assuming you receive pixel values in RGB form, another option is to convert the color to HSV (Hue - Saturation - Value). Pure green has (I believe) a hue value of 192.
This would make it easier to weight saturation and light levels differently than hue.
--
Scott
Also: hsv is sometimes better to use for color detection problems. For example, it is prooved that for human skin color detection, hsi (or hsv) model is much better, because it is closer to human color perception.
barrensoul
April 8th, 2005, 11:37 PM
How does HSV work? I've never heard of it
wsmmi6674
April 11th, 2005, 08:55 AM
Whereas RGB represents the Red, Green and Blue components of a color, HSV represents the Hue, Saturation, and Value (light- or dark-ness) components. Some feel it is a better match with the way humans think about color. You can covert RGB colors to HSV using the algorithm found here: http://www.cs.rit.edu/~ncs/color/t_convert.html
--
Scott
yiannakop
April 11th, 2005, 09:21 AM
HSV and HSI are 2 very similar color models. HSV stands for:
H (hue): Ranges from 0-360. In some cases it is normalized 0-100. Hue represents the COLOR type (e.g. blue, red etc).
S (saturation): Ranges from 0-100. It represents the "purity" of the color: the higher saturation value is, the clearer the color is. If saturation is low, the color looks closer to gray.
V (value): This is the brightness of the color, and it ranges from 0-100.
HSV model is sometimes represented as a cone. Try find a tutorial for explanation on this.
How to convert from RGB to HSV:
Suppose you have (R,G,B) values:
MAX = max(R,G,B)
MIN = min(R,G,B)
then:
H = ((G-B)/(MAX-MIN))*60 if MAX = R
(2+(B-R)/(MAX-MIN))*60 if MAX = G
(4+(R-G)/(MAX-MIN))*60 if MAX = B
S = (MAX-MIN)/MIN
V = MAX
Hope it helps,
Theodore :wave:
kimohoss
February 27th, 2007, 03:09 PM
hello yiannakop
please i want the matlab code because i need it urgently and as fast as possible in my graduation project thnx a lot.
kimohoss
March 5th, 2007, 07:51 AM
please i want the matlab code ,it's very urgent
my mail is kimohoss@hotmail.com
please iu want it as soon as possible
MrViggy
March 5th, 2007, 11:27 AM
You realize this post is almost 2 years old. It's possible Theodore isn't reading this forum anymore.
Viggy
yiannakop
March 26th, 2007, 07:39 AM
Well, that's true, I had not read the thread for a long period of time.
Anyway, probably it's too late, but here some code I wrote for color detection (though, the pseodo code I had given was, in my opinion quite clear and easy to be transposed to matlab code).
Anyway, the following code is a matlab function that takes the following arguments:
1) RGB: a MxNx3 matrix of the RGB values
2) mode: this argument should take the values 1,2 or 3, depending on the color you want to detect (red, green or blue).
3) thres: a threshold that is used to detect the desired color in the following way: if the desired color is LARGER than thres * (each of the other two colors), then the current pixel is labelled as 1 (color found).
function I = findColor(RGB, mode, thres)
% function BIN = findColor(RGB, rgbVal, Thres)
% Function for detecting a specific rgb value, within acceptable tollerance
% RGB: the rgb image
% mode: the color to detect:
% 1: red
% 2: green
% 3: blue
% thres: the distance tollerance
The plotted results are shown in the attached images.
PS1: Other threshold values can be used for more accurate color detection.
PS2: The thresholding method presented here is trivial. More sophisticated methods could also be used, that, for example would take into consideration the texture.
mwg
June 21st, 2007, 07:24 AM
and how do I do that in HSV?
yiannakop
June 21st, 2007, 08:56 AM
and how do I do that in HSV?
Well, in a similar way. I suppose you will have to check the hue scale mainly. For example, if you want to detect "RED" color you will have to search about pixels with values of H close to 0. If you are interested in "pure" red color then force the S (saturation) to be close to 100%. Otherwise, do not use the S component. Finally, you can put restrictions (with a tollerance) in the Value component. Anyway, if you are not interested in the brightness, do not use the V component, and if you are not interested in the "clearness" of the color do not use the S component.
To be more analytic, assume you want to detect red color. You have to decide if you want a specific brightness of the color (that is V) and a specific pureness of your color. To speak in "rgb terms", for example you want to detect RGB={150,0,0} (that has 100% saturation, since it is 100% pure red color). The questions above become:
1. do you also want to detect e.g. RGB={250,0,0} (that is, do you want to have tollerance in the V coefficient of the HSV space?) and
2. do you also want to detect, e.g. RGB = {60,10,10} which corresponds to lower S values?
yiannakop
June 22nd, 2007, 04:11 PM
and how do I do that in HSV?
I've also made an example function for you:
function colorDetectHSV(RGB, hsvVal, tol)
HSV = rgb2hsv(RGB);
% find the difference between required and real H value:
diffH = abs(HSV(:,:,1) - hsvVal(1));
if (length(tol)>1)
% find the difference between required and real S value:
diffS = abs(HSV(:,:,2) - hsvVal(2));
T2 = tol(2);
I2( find(diffS < T2) ) = 1;
if (length(tol)>2)
% find the difference between required and real V value:
difV = HSV(:,:,3) - hsvVal(3);
T3 = tol(3);
I3( find(diffS < T3) ) = 1;
I = I1.*I2.*I3;
else
I = I1.*I2;
end
else
I = I1;
end
The above function:
1. Takes as argument an rgb image (MxNx3), the hsv value you want to detect (this can be a vector 1x1 OR 2x1 OR 3x1) and a tolerance array (save size as hsv value)
2. Transposes the image to HSV.
3. Depending on the length L of tollerance (tol):
3.1: L=1: Searches ONLY the H coeficient and finds pixels that are close enough to hsv.
3.2: L=2: Searches H and S coeficients and finds pixels that are close enough to hsv (the 2 values given in the argument).
3.3. L=3: Searches ALL HSV componets.
Here is an example of how to call the above function (again with the trees image):
The above code calls the function for finding the hsv value [0.66 1.0 0.5] with tollerance [0.1 0.5 0.5]. We have to note that H = 0.66 stands for the blue color (tolerance: 0.1), S = 1.0 stands for 100% pure color (tolerance 0.50).
I attach the original and the detected image in the attached image.
PS: the HSV values in matlab are between 0 and 1.
:wave:
mwg
June 22nd, 2007, 04:46 PM
I really appreciate it!
thank you!!
tommy_chai
November 21st, 2007, 05:19 AM
Hi guys,
do you have any idea which one is better, RGB or HSV if i use it to detect lips or mouth?
The attachments below "image.zip" are images which i have tried with RGB. The moustache seems to be the noise.
Please help, i will appreciate every piece of comment.
yiannakop
November 22nd, 2007, 03:53 AM
Hi guys,
do you have any idea which one is better, RGB or HSV if i use it to detect lips or mouth?
The attachments below "image.zip" are images which i have tried with RGB. The moustache seems to be the noise.
Please help, i will appreciate every piece of comment.
Hi. First of all I believe HSV is better for colour detection (I've tried this in the past for "skin" detection and it worked better). Though, in order to test the above function I've written, you need some "training" data, i.e. some prior knowledge. In other words, you may need the average value of your object of interest (in that case lips).
The following function does the following:
Loads an image (which you provide as an RGB argument)
Waits for user clicks (right clicks) and for each click it selects an area (around the selected point) and it keeps the HSV (average) value of that area.
Finally, it calculates the average HSV value and it plots the progress of the average H, S, and V coefficients along mouse clicks.
function hsvMean = selectPixelsAndGetHSV(RGB, Area)
%
% function hsvMean = selectPixelsAndGetHSV(RGB, Area)
%
% Use this function in order to select multiple points from an image (use
% right click to stop process). The selected points are used to calculate
% the average HSV values.
% ARGUMENTS:
% RGB: the RGB image
% AREA: the area size used to calulate the HSV values of each point
%
%
% Theodoros Giannakopoulos - November 2007
%
I run the above m-file for one of your images (code: hsvMean = selectPixelsAndGetHSV(RGB1, 5);). In the following pictures you can see:
a) the initial image and the selected 5x5 areas in blue.
b) how the average H, S and V values were changed along time.
As you can see, the final HSV values are:
HSV = [0.0782 0.5461 0.3454].
Regards,
Theodore
RoboTact
November 22nd, 2007, 05:48 AM
Or even better don't stick to particular representation and allow a class of transformations that covers RGB, HSV and more and learn parameters appropriate for you task from training data. You'd need to understand some theory though.
tommy_chai
November 23rd, 2007, 05:02 AM
Thanks for the code.
Yiannakop: I have tried your codes. Let's say we get HSV = [0.0782 0.5461 0.3454] by running selectPixelsAndGetHSV(RGB, Area). Then only we use the mean to apply to your previous codes on HSV, colorDetectHSV(a, [0.0782 0.5461 0.3454], [0.3 0.5 0.5]). Is this what you mean?
I can get the mouth region in black pixels. Why? By right it should be detected in white pixels as shown by your example "tree".
This attachment "aa.pgm" is the result i get by using your RGB codes. It is the same image as you tried with HSV. I found that the result generated by RGB is better. Why? I have used the method as above.
Can you try to make the HSV automatically as the RGB code, in which we only need to fill in the threshold? This is because if i have a bigger database, does it mean that i need to mark every image to get the average for HSV? Can you help to make the HSV codes more automated in this case?
Anyway, thanks for sharing out the codes. At least i know HSV can do it but more complicated compared to RGB. Thank you very much.
yiannakop
November 26th, 2007, 04:25 AM
Ok I found were the problem was. As you can see, in the last function i sent you I finally keep the mean() (AVERAGE) value of the HSV values. I realized that this is incorrect: suppose that you select a pixel which has much different HSV values. Then, the average value will significally change (and that is much obvious in HSV values, where for example the H value differs alot from color to color). Therefore, I have decided to replace the mean() calls with median(), which is more robust against noise pixels. Now, the code becomes:
function hsvMean = selectPixelsAndGetHSV(RGB, Area)
%
% function hsvMean = selectPixelsAndGetHSV(RGB, Area)
%
% Use this function in order to select multiple points from an image (use
% right click to stop process). The selected points are used to calculate
% the average HSV values.
% ARGUMENTS:
% RGB: the RGB image
% AREA: the area size used to calulate the HSV values of each point
%
%
% Theodoros Giannakopoulos - November 2007
%
Can you try to make the HSV automatically as the RGB code, in which we only need to fill in the threshold? This is because if i have a bigger database, does it mean that i need to mark every image to get the average for HSV? Can you help to make the HSV codes more automated in this case?
Well I suppose it wouldn't be hard to use the hsv detect function i've written in a matlab script that reads multiple images from a folder and keep the median hsv value from all images. I know this is hard work, but this is generally a serious step in all pattern recognition problems: gathering and labelling training data... so you will have to get through this...... ;)
tommy_chai
November 26th, 2007, 11:39 AM
Yiannakop: Thanks for your guidance, really appreciated it. From my opinion,
colorDetectHSV(RGB1, [0.019 0.55 0.33], [0.01 0.02 0.02]);
we still have to fill in manually for HSV value which we can obtain by executing hsvMean = selectPixelsAndGetHSV(RGB, Area) right?
In order to make it automated, i need to make a link to connect the HSV value which is generated to automatically update in colorDetectHSV() right?
Good job my friend. Thanks again.
Best regards,
Tommy
(PS:Honestly, i haven't try your new program to use median() due to my workload but i iwill try it as soon as possible)
yiannakop
November 26th, 2007, 02:03 PM
Yiannakop: Thanks for your guidance, really appreciated it.
Any time :wave:
From my opinion,
colorDetectHSV(RGB1, [0.019 0.55 0.33], [0.01 0.02 0.02]);
we still have to fill in manually for HSV value which we can obtain by executing hsvMean = selectPixelsAndGetHSV(RGB, Area) right?
Yes you need to have a "manual" stage involving in your training process and that happens in general. So, yes you will have to execute selectPixelsAndGetHSV(), and to be 100% correct you will have to execute this on MANY images (which, in a way will form the training data set).
In order to make it automated, i need to make a link to connect the HSV value which is generated to automatically update in colorDetectHSV() right?
I am not sure I get this actually...
tommy_chai
November 27th, 2007, 03:27 AM
It is good enough already for me. In order to make it auto, it is my job anyway. Thanks.
juana
September 28th, 2010, 02:14 PM
anyone know how to recognize skin color in java~ do help me~very urgent~
Maejie
September 28th, 2010, 08:25 PM
human skin color is defined within some ranges ?
R belongsto [a,b]
G belongsto [c,d]
B belongsto [e,f]
Foreach pixel of a given image, getpixel return a value [0,255]
What's wrong with this method ?
Eri523
September 28th, 2010, 10:29 PM
human skin color is defined within some ranges ?
R belongsto [a,b]
G belongsto [c,d]
B belongsto [e,f]
Foreach pixel of a given image, getpixel return a value [0,255]
What's wrong with this method ?
The HSI color model much better resembles human perception than the RGB model. Just read the earlier posts in this thread to learn something about it.
Eri523
October 8th, 2010, 01:08 AM
anyone know how to recognize skin color in java~ do help me~very urgent~
Now, more than one week after your post, I'd like to mention that when I pointed you to this thread, I meant you should read it rather than post in it. Considering the age of the thread, I think it's unlikely that the members who wrote it are still monitoring it, at least not on a regular basis.
Didn't reading the thread give you any useful information?
avii
October 25th, 2010, 11:19 AM
i need to find two colors in an image : red and white regions such that the two colored regions are adjacent. Also is it possible to put bounding boxes around the above specified regions? thankyou
naemi
October 26th, 2010, 11:52 PM
Just use the code posted in this thread to discriminate between the two regions as black and white. Then go through all the pixels, and identify border pixels -- they are the ones that aren't surrounded by same-color pixels. At the same time group all border pixels that are adjacent to each other together, and you'll have a list of groups of pixels which is a list of outlines around each region.
DivZero
October 30th, 2010, 04:45 PM
I know this is an old thread and the topic seems to have shifted a little from the original question... but as I'm about to ask a question myself, I thought I'd just to go back to the original question in this thread ("How can I find the green pixels in my image?") as I didn't see a few possibly relevant things touched on in here and contribute first.
There's actually three things at play..
1. The method of determining which colors are green
2. Specifying what, exactly, 'green' is.
3. What color system you're using (ignoring that one in this post)
Is #00ff00 green?
What about #00cc00?
If you're looking just for those 'pure green' colors, then a bitmask will do.
Is #10ff00 green?
If you're looking for colors that are close enough to a pure green, then a hue lookup (either through conversion to HSV/HSL or not) with a threshold will do.
Now for a less simple example...
Is #8db600 or is #27a64c green (#00ff00)?
Conventional wisdom from looking at the numbers would indicate that the first is more of a yellow and the second is more of a green.
Looking at the hues for the first one, it is 73.5°.
For the second one, 137.5°.
In terms of hue, the second one -also- appears to be more green (120°), while the first appears to be quite a bit more yellow (60°).
Yet if you put all three colors up on your screen, odds are you'll find the first one to match the pure bright green more than the second one.
The reason for this is that human perception doesn't work like HSV/HSL space - it also doesn't work particularly like L*a*b space when it comes to comparing two colors (where one might take the euclidean distance).
It's actually a question that is answered ever-refinedly and the algorithms that try to give the answers in color difference are all shared under the nomer "Delta E".
http://en.wikipedia.org/Color_difference
Once you implement any of those algorithms (I suggest CMC 1:1 - it's fairly accurate without the heavy calculation and coding impact of CIEDE2000), you'll also quickly find that while both #00ff00 and #008000 are green, the range of similar colors varies wildly between these two along traditional hue axes and the like.. so you have to specify what 'green' is for such an algorithm to tell you what other colors in the image are similar to that 'green'.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.