8
$\begingroup$

I have to capture skin colour independent of illumination. I used the following criteria(using hsv and rgb) but it ain't working:

int h = get_hue(...);
int s = get_saturation(...);
int r = get_red_component(...);
int g = get_green_component(...);
int b = get_blue_component(...);

if ((h<38)&&(h>6)&&(s>0.23)&&(s<0.68)){
    // skin color
}
else if ((r>95) && (g>40) && (b>20) && 
         ((maximum(r,g,b)-minimum(r,g,b))>15) && 
         (abs(r-g)>15)&&(r>g)&&(r>b)){
   // also skin color
}

It works in the morning when my skin is illuminated but by evening it does not work.

Any Help will be appreciated. Thanks in Advance. (PS -my skin ain't white.)

$\endgroup$
  • 2
    $\begingroup$ Could you provide sample pictures, and maybe describe desired output a little better? Do you want to "classify" image pixels in to non-skin and skin classes? Also, could you try and justify your criteria, maybe it is not so bad but it would help us in improving it if we understood how you came up with it. $\endgroup$ – penelope Jun 5 '12 at 14:43
  • 2
    $\begingroup$ This might help (i.e. for removing effects of illumination first): dsp.stackexchange.com/a/459/35 $\endgroup$ – datageist Jun 5 '12 at 15:13
  • $\begingroup$ these two criteria I just obtained from googling and yes I've to distinguish skin from non skin areas $\endgroup$ – Roney Island Jun 5 '12 at 16:16
  • $\begingroup$ I found this citeseerx.ist.psu.edu/viewdoc/… $\endgroup$ – Roney Island Jun 6 '12 at 3:06
  • 1
    $\begingroup$ here is an old question of mine, maybe it could help: dsp.stackexchange.com/questions/1625/… $\endgroup$ – nkint Jun 19 '12 at 9:46
4
$\begingroup$

In my experience best method for this is converting it to Lab color space. L represents the light, and a and b are light independent. OpenCV supports Lab color scale conversion.

$\endgroup$
  • $\begingroup$ I've seen the same remark in the Face recognition handbook (Springer). Lab should be a better color space. $\endgroup$ – sansuiso Mar 7 '13 at 7:40
2
$\begingroup$

For this special case, I recommend reading up on LAB Color model.

And in regard to the LAB Color model, read up on Delta E. The distance between 2 colors. More details about color space can be found here: http://www.codeproject.com/Articles/613798/Colorspaces-and-Conversions

I have never attempted the LAB color model via OpenCV as it's is a hassle to convert from RGB to LAB and back(requires an immediate step).

But I have explored Delta E on MatLab to great success. You have to select the skin first, draw a small ROI on the video/picture and the program will find all the exact same color tone as the skin you selected via the ROI.

Another option is also look into the texture. A short preview here: http://books.google.com.sg/books?id=bRlk_WjfITIC&pg=PA598&lpg=PA598&dq=skin+thresholding+from+texture&source=bl&ots=28fE0livyh&sig=8EeQTLFCc-JB979_-ccyrhDJlqA&hl=en&sa=X&ei=aAuFUsHhJoWJrQfpkoCgBg&ved=0CDUQ6AEwAQ#v=onepage&q=skin%20thresholding%20from%20texture&f=false

This is basically training a image database. Comment here if you need help to training the image database or conversion of ColorSpace. A little busy, so the answer is just suggestions that you can do. Cheers.

$\endgroup$
1
$\begingroup$

try this:

''' Detect human skin tone and draw a boundary around it.
Useful for gesture recognition and motion tracking.

Inspired by: http://stackoverflow.com/a/14756351/1463143

Date: 08 June 2013
'''

# Required moduls
import cv2
import numpy

# Constants for finding range of skin color in YCrCb
min_YCrCb = numpy.array([0,133,77],numpy.uint8)
max_YCrCb = numpy.array([255,173,127],numpy.uint8)

# Create a window to display the camera feed
cv2.namedWindow('Camera Output')

# Get pointer to video frames from primary device
videoFrame = cv2.VideoCapture(0)

# Process the video frames
keyPressed = -1 # -1 indicates no key pressed

while(keyPressed < 0): # any key pressed has a value >= 0

    # Grab video frame, decode it and return next video frame
    readSucsess, sourceImage = videoFrame.read()

    # Convert image to YCrCb
    imageYCrCb = cv2.cvtColor(sourceImage,cv2.COLOR_BGR2YCR_CB)

    # Find region with skin tone in YCrCb image
    skinRegion = cv2.inRange(imageYCrCb,min_YCrCb,max_YCrCb)

    # Do contour detection on skin region
    contours, hierarchy = cv2.findContours(skinRegion, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # Draw the contour on the source image
    for i, c in enumerate(contours):
        area = cv2.contourArea(c)
        if area > 1000:
            cv2.drawContours(sourceImage, contours, i, (0, 255, 0), 3)

    # Display the source image
    cv2.imshow('Camera Output',sourceImage)

    # Check for user input to close program
    keyPressed = cv2.waitKey(1) # wait 1 milisecond in each iteration of while loop

# Close window and camera after exiting the while loop
cv2.destroyWindow('Camera Output')
videoFrame.release()
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.