grundlegende hsb hauterkennung, neonbeleuchtung


14

Ich hoffe, das ist der richtige Ort, um zu fragen. ansonsten entschuldige meinen fehler und rate mir bitte eine bessere seite.

Ich versuche, einen supereinfachen Hautdetektor mit einer Reihe von HSB-Bildern zu implementieren. Ich benutze den hier und hier beschriebenen Ansatz .

Ich versuche, eine Videoquelle von meiner Webcam zu verwenden. Wenn ich Sonnenlicht benutze, funktioniert es ganz gut (nicht so gut, aber ganz gut), aber mit Neonlicht. Es ist ein Durcheinander. Überall werden viel weiße Bereiche und viel Rauschen erkannt.

Warum?

Ich verwende den in der zweiten Quelle beschriebenen Algorithmus :

  1. Bild in HSV-Farbraum umwandeln
  2. Setze Weiß in den Bereich 0 <H <38
  3. Filter erweitern
  4. Filter abtragen
  5. Filter verwischen

Bildbeschreibung hier eingeben

Antworten:


10

Dies funktioniert möglicherweise besser mit einem einfachen generativen Modell in RGB als mit HSV.

  1. Holen Sie sich ein Trainingsbild oder mehrere Trainingsbilder mit etwas Haut.
  2. Wählen Sie die Skin-Pixel manuell aus (z. B. durch Erstellen einer Binärmaske).
  3. Berechnen Sie den Mittelwert und die Kovarianz des Hautfarbtons in RGB (jeder sollte aus 3 Elementen bestehen).
  4. Berechnen Sie für ein unbekanntes Pixel seinen Mahalanobis-Abstand vom Mittelwert unter Verwendung der Kovarianz.
  5. Klassifizieren Sie es als Skin, wenn der Abstand unter einem Schwellenwert liegt.
  6. Stellen Sie den Schwellenwert auf die beste Leistung ein.

Bearbeiten: Ich weiß nicht, ob OpenCV eine Funktion zum Berechnen der Kovarianz hat, aber ich kann Ihnen sagen, wie es selbst geht. Angenommen, Sie haben RGB-Pixel. Sie legen sie in eine n x 3 Matrix, nennen wir es P . Berechnen Sie dann m , den mittleren RGB-Vektor, indem Sie den Durchschnitt der Spalten berechnen. m wird ein 1 x 3 Vektor sein. Subtrahieren Sie m von jeder Zeile von P und rufen Sie die resultierende Matrix Q auf . Nun zu berechnen Kovarianz, alles , was Sie tun müssen, ist mehrfach Q durch die Transponierung von selbst: C = Q ' Q . Stellen Sie sicher, dass CnnPmmmPQ.Q.C=Q.Q.C ist 3 x 3.

Edit2: Die Werte, die Sie erhalten, scheinen zu groß zu sein. Um die maximale Kovarianz zu erhalten, erstellen Sie die folgende Matrix:

255 255 255
 0   0   0

und Kovarianz davon berechnen. Sie sollten eine Matrix erhalten, in der jeder Wert ungefähr 32513 ist. Stellen Sie also sicher, dass Ihre Pixelwerte zwischen 0 und 255 liegen, und kopieren Sie sie korrekt in Floats oder Doubles. Der Mahalanobis-Abstand wird in Varianz-Einheiten angegeben, daher sollten die Zahlen klein sein. Ihr Schwellenwert für die Hautklassifizierung sollte wahrscheinlich unter 4 liegen.


Ich habe ein Problem beim Verstehen, wie man eine 3x3-Kovarianzmatrix mit opencv aus einem Bild erhält. Können Sie mir einen Hinweis geben?
nkint

@nkint, siehe bearbeitete Antwort.
Dima

ok toll In 5 Zeilen haben Sie mir gezeigt, was Kovarianz ist. Vielen Dank. Es klappt. aber ich habe ein Problem beim Speichern der Ergebnisse. Wenn ich Pixel von 0-255 habe, welche Art von Zahlen muss ich von Mahalanobis Entfernung erwarten? Wenn ich sie in einer 8-Uint lagere, nimmt es nur einen kleinen Teil der Haut, wenn ich sie in einer 32-Float lagere, bekomme ich merkwürdiges weißes Rauschen
nkint

Ja, ich glaube, ich mache etwas falsch, weil meine Kovarianzmatrix wie folgt lautet: [10913058.00000000, 7046611.50000000, 3290781.50000000; 7046611.50000000, 4811646.00000000, 2225078.00000000; 3290781.50000000, 2225078.00000000, 1387631.87500000]
nkint

1
Sie können sich die Kovarianz als Definition eines Ellipsoids in 3D vorstellen. Möglicherweise können Sie es in Matlab visualisieren, aber das ist wahrscheinlich eine Menge Arbeit. Alternativ können Sie versuchen, 2D-Projektionen des Ellipsoids zu betrachten, aber das würde auch einige Arbeit erfordern.
Dima

4

Berücksichtigen Sie die unterschiedlichen Werte, die in der HSV-Farbe erhalten werden, wenn Neonlicht angewendet wird: Ein Beispiel für die Abweichung ist hier . Passen Sie Ihren Algorithmus an diese Werte an.

Hier gibt es einen anderen Algorithmus , um die Haut zu erkennen und Lichtverhältnisse zum Erkennen können Sie verwenden diese ein .

Ein anderer Algorithmus, der mit der Hauterkennung zusammenhängt, aber nicht zu sehr mit Neonlichteffekten zusammenhängt, ist dieser .


2

Die Antworten, die Sie bisher erhalten haben, deuten auf gute alternative Methoden hin. Wenn Sie jedoch an der Verwendung Ihres ursprünglichen Algorithmus interessiert sind, ist dies wahrscheinlich nicht schwer zu beheben. Sie müssen sich nur an die HSV-Besonderheiten von OpenCV anpassen. Angesichts der verrückten Ergebnisse nehme ich an, dass Sie bei der Auswahl Ihrer Schwellenwerte und / oder bei der Konvertierung von Pixeln wahrscheinlich eine der gebräuchlichsten numerischen Darstellungen von HSV verwendet haben.

OpenCV stellt HSV anders dar als die meisten anderen Quellen, die Sie möglicherweise gefunden haben:

  • Der größte Unterschied für Sie wäre w / r / t Farbton: OpenCV repräsentiert einen Farbton im Bereich von 0 bis 179, wenn fast alles andere das hängende Bit ausnutzt, um mehr Informationen zu erhalten, w / 0-255.
  • Der andere Unterschied: Die Messung der Sättigung ist gegenüber der Norm invertiert. 255 Sättigung bedeutet also hell in opencv, statt weiß (beachten Sie, wir sind wieder bei 255 - nur der Farbton ist 0-180, vielleicht wegen der "Rad" -Darstellung?)

Wahrscheinlich zu spät, um Ihnen zu helfen, aber es war eine interessante Frage, und jemand anderes könnte auf dasselbe Problem stoßen.


-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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.