podstawowe wykrywanie skóry HSB, oświetlenie neonowe


14

mam nadzieję, że jest to właściwe miejsce, aby zapytać. w innym przypadku przepraszam za mój błąd i proszę o poradę, żebym był lepszy.

Próbuję wdrożyć super prosty wykrywacz skóry przy użyciu pewnego zakresu obrazu HSB. używam podejścia opisanego tutaj i tutaj .

próbuję użyć źródła wideo z mojej kamery internetowej. jeśli użyję oświetlenia słonecznego, działa całkiem dobrze (nie tak dobrze, ale całkiem dobrze), ale przy świetle neonowym… to jest bałagan. wykryto wiele białych obszarów i wszędzie dużo hałasu.

dlaczego?

używam algorytmu opisanego w drugim źródle :

  1. konwersja obrazu ho przestrzeni barw HSV
  2. umieść biały w zakresie 0 <H <38
  3. filtr rozszerzający
  4. filtr erodujący
  5. filtr rozmycia

wprowadź opis zdjęcia tutaj

Odpowiedzi:


10

To może faktycznie działać lepiej, używając prostego modelu generatywnego w RGB zamiast HSV.

  1. Uzyskaj obraz treningowy lub kilka obrazów treningowych z odrobiną skóry.
  2. Ręcznie wybierz piksele skóry (np. Tworząc maskę binarną)
  3. Oblicz średnią i kowariancję odcienia skóry w RGB (każdy powinien być wektorem 3-elementowym)
  4. W przypadku nieznanego piksela obliczyć jego odległość Mahalanobisa od średniej, używając kowariancji.
  5. Sklasyfikuj jako skórę, jeśli odległość jest mniejsza niż próg.
  6. Dostosuj próg, aby uzyskać najlepszą wydajność.

Edytować:nnP.mmmP.QQdo=QQdo wynosi 3 x 3.

Edycja2: Otrzymywane wartości wydają się zbyt duże. Aby uzyskać maksymalną kowariancję, należy utworzyć następującą macierz:

255 255 255
 0   0   0

i obliczyć kowariancję tego. Powinieneś dostać macierz, w której każda wartość wynosi około 32513. Upewnij się więc, że twoje wartości w pikselach wynoszą od 0 do 255, i upewnij się, że skopiowałeś je do liczb zmiennoprzecinkowych lub podwójnych. Odległość Mahalanobisa jest wyrażona w jednostkach wariancji, dlatego liczby powinny być małe. Twój próg klasyfikacji skóry powinien być prawdopodobnie mniejszy niż 4.


mam problem ze zrozumieniem, w jaki sposób uzyskać macierz kowariancji 3x3 z opencv z obrazu .. czy możesz podać jakieś odniesienie?
nkint

@ nkint, zobacz edytowaną odpowiedź.
Dima

ok świetnie. w 5 liniach pokazałeś mi, czym jest kowariancja. dzięki. to działa. ale mam problem z przechowywaniem wyników. jeśli mam piksele od 0-255, jakiego rodzaju liczb powinienem oczekiwać od odległości Mahalanobisa? jeśli przechowuję je w 8-uint, zajmuje to tylko niewielką część skóry, jeśli przechowuję je w 32-float, mam dziwny biały szum
nkint

tak, myślę, że robię coś źle, ponieważ moja macierz kowariancji to: [10913058.00000000, 7046611.50000000, 3290781.50000000; 7046611.50000000, 4811646.00000000, 2225078.00000000; 3290781.50000000, 2225078.00000000, 1387631.87500000]
nkint

1
Możesz pomyśleć o kowariancji jako o zdefiniowaniu elipsoidy w 3D. Być może będziesz w stanie wyobrazić sobie to w Matlabie, ale prawdopodobnie będzie to dużo pracy. Alternatywnie, możesz spróbować spojrzeć na rzuty elipsoidy 2D, ale to również zajmie trochę pracy.
Dima,

4

Weź pod uwagę różne wartości uzyskane w kolorze HSV przy zastosowaniu światła neonowego: przykład jego odchylenia jest tutaj . Spróbuj dostosować algorytm, aby dostosował się do tych wartości.

Tutaj jest inny algorytm do wykrywania skóry, a do wykrywania warunków świetlnych możesz użyć tego .

Kolejny algorytm związany z wykrywaniem skóry, ale niezbyt związany z efektami światła neonowego, to ten .


2

Odpowiedzi, które otrzymałeś do tej pory, wskazują na dobre alternatywne metody, ale jeśli jesteś zainteresowany użyciem czegoś takiego jak początkowy algorytm, prawdopodobnie nie jest to trudne. Musisz tylko dostosować się do osobliwości HSV OpenCV. Biorąc pod uwagę dziwne wyniki, zakładam, że prawdopodobnie użyłeś jednej z bardziej powszechnych reprezentacji numerycznych HSV przy wybieraniu progów i / lub przy konwersji pikseli?

OpenCV reprezentuje HSV inaczej niż większość innych źródeł, które mogłeś znaleźć:

  • Największą różnicą byłbyś w / r / t odcień: OpenCV reprezentuje odcień w zakresie od 0 do 179, gdy prawie wszystko inne wykorzystuje bit wiszący, aby zachować więcej informacji, w / 0-255.
  • Druga różnica: pomiar nasycenia jest odwrócony w stosunku do normy. Zatem nasycenie 255 oznacza jasne w opencv, zamiast białego (zauważ, wróciliśmy do 255 - tylko odcień to 0-180, być może z powodu reprezentacji „koła”?)

Prawdopodobnie za późno, aby ci pomóc, ale było to interesujące pytanie, a ktoś inny może napotkać ten sam problem.


-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)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.