détection de base de la peau hsb, éclairage néon

14

j'espère que c'est le bon endroit pour demander. Sinon, désolé pour mon erreur et pleace me conseille un meilleur site.

J'essaye d'implémenter un détecteur de peau super simple en utilisant une certaine gamme d'images HSB. j'utilise l'approche décrite ici et ici .

j'essaye d'utiliser une source vidéo de ma webcam. si j'utilise un éclairage solaire, cela fonctionne assez bien (pas si bon mais assez bon), mais avec des néons .. c'est un gâchis. beaucoup de régions blanches sont détectées et beaucoup de bruit partout.

Pourquoi?

j'utilise l'algorithme décrit dans la deuxième source :

  1. convertir l'image ho l'espace colorimétrique HSV
  2. mettre du blanc sur la plage 0 <H <38
  3. filtre dilaté
  4. éroder le filtre
  5. filtre flou

entrez la description de l'image ici

nkint
la source

Réponses:

10

En fait, cela pourrait mieux fonctionner en utilisant un modèle génératif simple en RVB plutôt qu'en HSV.

  1. Obtenez une image d'entraînement ou plusieurs images d'entraînement avec un peu de peau.
  2. Sélectionnez manuellement les pixels de la peau (par exemple en créant un masque binaire)
  3. Calculez la moyenne et la covariance du teint en RVB (chacun doit être des vecteurs à 3 éléments)
  4. Pour un pixel inconnu, calculez sa distance de Mahalanobis à partir de la moyenne, en utilisant la covariance.
  5. Classez-le comme peau si la distance est inférieure à un seuil.
  6. Ajustez le seuil pour de meilleures performances.

nnPmmmPQQC=QQC est 3 x 3.

Edit2: Les valeurs que vous obtenez semblent être trop grandes. Pour obtenir la covariance maximale, créez la matrice suivante:

255 255 255
 0   0   0

et calculer la covariance de cela. Vous devriez obtenir une matrice où chaque valeur est d'environ 32513. Assurez-vous donc que vos valeurs de pixels vont de 0 à 255, et assurez-vous de les copier dans des flottants ou de doubler correctement. La distance de Mahalanobis est dans les unités de variance, donc pour que les nombres soient petits. Votre seuil de classification de la peau devrait probablement être inférieur à 4.

Dima
la source
j'ai du mal à comprendre comment obtenir une matrice de covariance 3x3 avec opencv à partir d'une image .. pouvez-vous me donner une référence?
nkint
@nkint, veuillez consulter la réponse modifiée.
Dima
D'accord, super. en 5 lignes vous m'avez fait comprendre ce qu'est la covariance. Merci. Ça marche. mais j'ai du mal à stocker les résultats. si j'ai des pixels de 0 à 255, quel genre de nombres dois-je attendre de la distance de Mahalanobis? si je les stocke dans un 8 uint, cela ne prend qu'une petite partie de la peau, si je les stocke dans un 32 flotteurs, j'obtiens un bruit blanc
étrange
ouais je pense que je fais quelque chose de mal parce que ma matrice de covariance est: [10913058.00000000, 7046611.50000000, 3290781.50000000; 7046611.50000000, 4811646.00000000, 2225078.00000000; 3290781.50000000, 2225078.00000000, 1387631.87500000]
nkint
1
Vous pouvez considérer la covariance comme définissant un ellipsoïde en 3D. Vous pourrez peut-être le visualiser dans Matlab, mais cela demandera probablement beaucoup de travail. Alternativement, vous pouvez essayer de regarder les projections 2D de l'ellipsoïde, mais cela prendrait également un peu de travail.
Dima
4

Prendre en compte les différentes valeurs obtenues en couleur HSV lors de l'application de néons: un exemple de son écart est ici . Essayez d'adapter votre algorithme pour l'adapter à ces valeurs.

Ici, il existe un autre algorithme pour détecter la peau, et pour détecter les conditions d'éclairage, vous pouvez utiliser celui-ci .

Un autre algorithme, lié à la détection de la peau, mais pas trop lié aux effets de lumière néon, est celui-ci .

Luis Andrés García
la source
2

Les réponses que vous avez obtenues jusqu'à présent indiquent de bonnes méthodes alternatives, mais si vous êtes intéressé à utiliser quelque chose comme votre algorithme initial, ce n'est probablement pas difficile à corriger. Il vous suffit de régler les particularités HSV d'OpenCV. Compte tenu des résultats farfelus, je suppose que vous avez probablement utilisé l'une des représentations numériques les plus courantes du HSV pour choisir vos seuils et / ou pour convertir des pixels?

OpenCV représente HSV différemment de la plupart des autres sources que vous pourriez avoir trouvées:

  • La plus grande différence pour vous serait w / r / t hue: OpenCV représente la teinte allant de 0 à 179, quand presque tout le reste profite du bit de suspension pour conserver plus d'informations, w / 0-255.
  • L'autre différence: la mesure de la saturation est inversée par rapport à la norme. Donc, 255 saturation signifie lumineux en opencv, au lieu de blanc (remarquez, nous sommes de retour à 255 - seule la teinte est 0-180, peut-être à cause de la représentation de la `` roue ''?)

Probablement trop tard pour vous aider, mais c'était une question intéressante, et quelqu'un d'autre pourrait rencontrer le même problème.

Profane
la source
-1
import sys
import numpy
import cv2

cap = cv2.VideoCapture(0)
while(1):
    _, im = cap.read()

    im_ycrcb = cv2.cvtColor(im, cv2.COLOR_BGR2YCR_CB)

    skin_ycrcb_mint = numpy.array((0, 133, 77))
    skin_ycrcb_maxt = numpy.array((255, 173, 127))
    skin_ycrcb = cv2.inRange(im_ycrcb, skin_ycrcb_mint, skin_ycrcb_maxt)

    cv2.imshow("Second Image", skin_ycrcb) # Second image
    contours, _ = cv2.findContours(skin_ycrcb, cv2.RETR_EXTERNAL, 
        cv2.CHAIN_APPROX_SIMPLE)
    for i, c in enumerate(contours):
        area = cv2.contourArea(c)
            if area > 1000:
                cv2.drawContours(im, contours, i, (255, 0, 0), 3)
    cv2.imshow("Final Image", im)         # Final image
    cv2.waitKey(1)
Surendra Patil
la source