Détection OpenCV invariante de la couleur de la peau avec des changements d'éclairage

8

Je dois capturer la couleur de la peau indépendamment de l'éclairage. J'ai utilisé les critères suivants (en utilisant hsv et rgb) mais cela ne fonctionne pas:

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
}

Cela fonctionne le matin quand ma peau est illuminée mais le soir ça ne marche pas.

Toute aide serait appréciée. Merci d'avance. (PS - ma peau n'est pas blanche.)

Roney Island
la source
2
Pourriez-vous fournir des exemples d'images et peut-être décrire un peu mieux la sortie souhaitée? Voulez-vous "classer" les pixels de l'image dans des classes non-skin et skin ? Aussi, pourriez-vous essayer de justifier vos critères, peut-être que ce n'est pas si mal, mais cela nous aiderait à l'améliorer si nous comprenions comment vous en êtes arrivé à cela.
penelope
2
Cela pourrait aider (c'est-à-dire pour supprimer d'abord les effets d'éclairage): dsp.stackexchange.com/a/459/35
datageist
ces deux critères que je viens d'obtenir de googler et oui je dois distinguer la peau des zones non cutanées
Roney Island
J'ai trouvé ce citeseerx.ist.psu.edu/viewdoc/…
Roney Island
1
voici une vieille question à moi, cela pourrait peut-être aider: dsp.stackexchange.com/questions/1625/…
nkint

Réponses:

4

D'après mon expérience, la meilleure méthode consiste à le convertir en espace colorimétrique Lab. L représente la lumière, et a et b sont indépendants de la lumière. OpenCV prend en charge la conversion d'échelle de couleurs Lab.

Vladimir Perković
la source
J'ai vu la même remarque dans le manuel de reconnaissance faciale (Springer). Le laboratoire devrait être un meilleur espace colorimétrique.
sansuiso
2

Pour ce cas particulier, je recommande de lire le modèle LAB Color.

Et en ce qui concerne le modèle LAB Color, lisez Delta E. La distance entre 2 couleurs. Plus de détails sur l'espace colorimétrique peuvent être trouvés ici: http://www.codeproject.com/Articles/613798/Colorspaces-and-Conversions

Je n'ai jamais essayé le modèle de couleur LAB via OpenCV car il est difficile de convertir de RVB en LAB et vice-versa (nécessite une étape immédiate).

Mais j'ai exploré Delta E sur MatLab avec beaucoup de succès. Vous devez d'abord sélectionner le skin, dessiner un petit ROI sur la vidéo / image et le programme trouvera exactement la même tonalité de couleur que le skin que vous avez sélectionné via le ROI.

Une autre option consiste également à examiner la texture. Un bref aperçu ici: 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_-ccAhFJHUF = 0CDUQ6AEwAQ # v = onepage & q = skin% 20thresholding% 20from% 20texture & f = false

Il s'agit essentiellement de former une base de données d'images. Commentez ici si vous avez besoin d'aide pour former la base de données d'images ou pour convertir ColorSpace. Un peu occupé, donc la réponse est juste des suggestions que vous pouvez faire. À votre santé.

rockinfresh
la source
1

essaye ça:

''' 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()
samkhan13
la source