rilevazione di base della pelle hsb, illuminazione al neon


14

spero che questo sia il posto giusto per chiedere altrimenti scusatemi per il mio errore e vi prego di consigliarmi un sito migliore.

Sto cercando di implementare un rilevatore di skin super semplice usando una gamma di immagini hsb. sto usando l'approccio descritto qui e qui .

sto provando a usare una fonte video dalla mia webcam. se uso l'illuminazione solare funziona abbastanza bene (non così buono ma abbastanza buono), ma con la luce al neon .. è un casino. viene rilevata molta regione bianca e molto rumore ovunque.

perché?

sto usando l'algoritmo descritto nella seconda fonte :

  1. converti immagine nello spazio colore HSV
  2. metti il ​​bianco nell'intervallo 0 <H <38
  3. dilatare il filtro
  4. erode filter
  5. filtro sfocatura

inserisci qui la descrizione dell'immagine

Risposte:


10

Questo potrebbe effettivamente funzionare meglio usando un semplice modello generativo in RGB piuttosto che HSV.

  1. Ottieni un'immagine di allenamento o diverse immagini di allenamento con un po 'di pelle.
  2. Seleziona manualmente i pixel della skin (ad es. Creando una maschera binaria)
  3. Calcola la media e la covarianza del tono della pelle in RGB (ognuno dovrebbe essere un vettore a 3 elementi)
  4. Per un pixel sconosciuto, calcola la sua distanza di Mahalanobis dalla media, usando la covarianza.
  5. Classificalo come skin se la distanza è inferiore a una soglia.
  6. Ottimizza la soglia per le migliori prestazioni.

Modifica: non so se OpenCV ha una funzione per calcolare la covarianza, ma posso dirti come farlo da solo. Supponiamo che tu abbia pixel RGB. Li metti in un n x 3 matrici, chiamiamolo P . Quindi calcola , che è il vettore RGB medio calcolando la media delle colonne. sarà un vettore 1 x 3. Sottrarre da ogni fila di e chiamare la risultante matrice . Ora per calcolare la covarianza, tutto ciò che devi fare è moltiplicare per la trasposizione di se stesso: . Assicurati che sia 3 x 3.nnPmmmPQQC=Q'QC

Modifica2: i valori che stai ottenendo sembrano essere troppo grandi. Per ottenere la massima covarianza creare la seguente matrice:

255 255 255
 0   0   0

e calcolare la covarianza di ciò. Dovresti ottenere una matrice in cui ogni valore è approssimativamente 32513. Quindi assicurati che i valori dei pixel siano compresi tra 0 e 255 e assicurati di copiarli in float o raddoppia correttamente. La distanza di Mahalanobis è espressa in unità di varianza, quindi i numeri dovrebbero essere piccoli. La soglia per la classificazione della pelle dovrebbe essere probabilmente inferiore a 4.


ho problemi a capire come ottenere una matrice di covarianza 3x3 con opencv da un'immagine .. mi puoi dare qualche riferimento?
nkint

@nkint, vedere la risposta modificata.
Dima,

ok fantastico. in 5 righe mi hai fatto capire cos'è la covarianza. Grazie. Funziona. ma ho problemi a memorizzare i risultati. se ho pixel da 0 a 255 che tipo di numeri dovrei aspettarmi dalla distanza di Mahalanobis? se li
conservo in un ottavo

sì, penso di fare qualcosa di sbagliato perché la mia matrice di covarianza è: [10913058.00000000, 7046611.50000000, 3290781.50000000; 7046611.50000000, 4811646.00000000, 2225078.00000000; 3290781.50000000, 2225078.00000000, 1387631.87500000]
nkint

1
Puoi pensare alla covarianza come a definire un ellissoide in 3D. Potresti essere in grado di visualizzarlo in Matlab, ma è probabile che ci vorrà molto lavoro. In alternativa, puoi provare a guardare le proiezioni 2D dell'ellissoide, ma ci vorrebbe anche del lavoro.
Dima,

4

Prendi in considerazione i diversi valori ottenuti nel colore HSV quando viene applicata la luce al neon: un esempio della sua deviazione è qui . Prova ad adattare il tuo algoritmo in modo che si adatti a questi valori.

Qui c'è un altro algoritmo per rilevare la pelle e per rilevare le condizioni di luce è possibile utilizzare questo .

Un altro algoritmo, correlato al rilevamento della pelle, ma non troppo legato agli effetti della luce al neon, è questo .


2

Le risposte che hai ottenuto finora indicano buoni metodi alternativi, ma se sei interessato a utilizzare qualcosa come il tuo algoritmo iniziale, probabilmente non è difficile da risolvere. Devi solo adattarti alle peculiarità di HSV di OpenCV. Dati i risultati stravaganti, presumo che tu abbia probabilmente usato una delle rappresentazioni numeriche più comuni di HSV nella scelta delle tue soglie e / o nella conversione dei pixel?

OpenCV rappresenta HSV in modo diverso rispetto alla maggior parte delle altre fonti che potresti aver trovato:

  • La differenza più grande per te sarebbe w / r / t hue: OpenCV rappresenta la tonalità che va da 0 a 179, quando quasi tutto il resto sfrutta il bit di sospensione per conservare più informazioni, w / 0-255.
  • L'altra differenza: la misurazione della saturazione è invertita rispetto alla norma. Quindi 255 saturazione significa luminoso in opencv, anziché bianco (notate, siamo tornati a 255 - solo la tonalità è 0-180, forse a causa della rappresentazione della 'ruota'?)

Probabilmente è troppo tardi per aiutarti, ma era una domanda interessante e qualcun altro potrebbe incorrere nello stesso problema.


-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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.