detección básica de piel hsb, iluminación de neón

14

Espero que este sea el lugar correcto para preguntar. de todos modos perdon por mi error y por favor me aconsejan un sitio mejor.

Estoy tratando de implementar un detector de piel súper simple usando algún rango de imagen hsb. Estoy usando el enfoque descrito aquí y aquí .

Estoy tratando de usar una fuente de video de mi cámara web. si uso la iluminación solar funciona bastante bien (no tan bien pero bastante bien), pero con luz de neón ... es un desastre. se detectan muchas regiones blancas y mucho ruido en todas partes.

¿por qué?

Estoy usando el algoritmo descrito en la segunda fuente :

  1. convertir imagen ho espacio de color HSV
  2. poner blanco en el rango 0 <H <38
  3. filtro dilatador
  4. filtro de erosión
  5. filtro de desenfoque

ingrese la descripción de la imagen aquí

nkint
fuente

Respuestas:

10

En realidad, esto podría funcionar mejor usando un modelo generativo simple en RGB en lugar de HSV.

  1. Obtenga una imagen de entrenamiento o varias imágenes de entrenamiento con algo de piel.
  2. Seleccione manualmente los píxeles de la máscara (por ejemplo, creando una máscara binaria)
  3. Calcule la media y la covarianza del tono de piel en RGB (cada uno debe ser vectores de 3 elementos)
  4. Para un píxel desconocido, calcule su distancia de Mahalanobis desde la media, usando la covarianza.
  5. Clasifíquelo como máscara si la distancia es menor que un umbral.
  6. Ajuste el umbral para obtener el mejor rendimiento.

Editar: No sé si OpenCV tiene una función para calcular la covarianza, pero puedo decirte cómo hacerlo tú mismo. Digamos que tienes píxeles RGB. Se los pone en un n x 3 matriz, llamémosle P . Luego calcule m , que es el vector RGB medio calculando el promedio de las columnas. m será un vector 1 x 3. Restar m de cada fila de P y llamar a la matriz resultante Q . Ahora a la covarianza de computación, todo lo que tiene que hacer es multiplicar Q por la transpuesta de sí mismo: C = Q ' Q . Asegúrese de que CnortenortePAGmetrometrometroPAGQQC=QQC es 3 x 3.

Edit2: los valores que está obteniendo parecen ser demasiado grandes. Para obtener la covarianza máxima, cree la siguiente matriz:

255 255 255
 0   0   0

y calcular la covarianza de eso. Debería obtener una matriz donde cada valor sea aproximadamente 32513. Por lo tanto, asegúrese de que sus valores de píxeles oscilan entre 0 y 255, y asegúrese de copiarlos en flotantes o dobles correctamente. La distancia de Mahalanobis está en las unidades de varianza, por lo que los números deben ser pequeños. Su umbral para la clasificación de la piel probablemente debería ser inferior a 4.

Dima
fuente
Tengo problemas para entender cómo obtener una matriz de covarianza 3x3 con opencv de una imagen ... ¿me puede dar alguna referencia?
nkint
@nkint, vea la respuesta editada.
Dima
vale genial. en 5 líneas me hiciste entender qué es la covarianza. Gracias. funciona. pero tengo problemas para almacenar resultados. si tengo píxeles del 0 al 255, ¿qué tipo de números debo esperar de la distancia de Mahalanobis? si los guardo en un 8-uint, solo toma una pequeña parte de la piel, si los
guardo
Sí, creo que estoy haciendo algo mal porque mi matriz de covarianza es: [10913058.00000000, 7046611.50000000, 3290781.50000000; 7046611.50000000, 4811646.00000000, 2225078.00000000; 3290781.50000000, 2225078.00000000, 1387631.87500000]
nkint
1
Puede pensar en la covarianza como la definición de un elipsoide en 3D. Es posible que pueda visualizarlo en Matlab, pero es probable que sea mucho trabajo. Alternativamente, puede intentar mirar las proyecciones 2D del elipsoide, pero eso también requeriría algo de trabajo.
Dima
4

Tenga en cuenta los diferentes valores obtenidos en el color HSV cuando se aplica luz de neón: un ejemplo de su desviación está aquí . Intente adaptar su algoritmo para que se adapte a estos valores.

Aquí hay otro algoritmo para detectar la piel, y para detectar condiciones de luz puede usar este .

Otro algoritmo, relacionado con la detección de la piel, pero no demasiado relacionado con los efectos de luz de neón, es este .

Luis Andrés García
fuente
2

Las respuestas que ha obtenido hasta ahora apuntan a buenos métodos alternativos, pero si está interesado en usar algo como su algoritmo inicial, probablemente no sea difícil de solucionar. Solo necesita ajustar las peculiaridades HSV de OpenCV. Dados los resultados extravagantes, supongo que probablemente usó una de las representaciones numéricas más comunes de HSV al elegir sus umbrales y / o convertir píxeles.

OpenCV representa HSV de manera diferente a la mayoría de las otras fuentes que podría haber encontrado:

  • La mayor diferencia para usted sería w / r / t hue: OpenCV representa el tono que va de 0 a 179, cuando casi todo lo demás aprovecha el bit colgante para preservar más información, w / 0-255.
  • La otra diferencia: la medición de la saturación se invierte en comparación con la norma. Entonces, la saturación 255 significa brillante en opencv, en lugar de blanco (observe, volvemos a 255, solo el tono es 0-180, ¿tal vez debido a la representación de la 'rueda'?)

Probablemente sea demasiado tarde para ayudarlo, pero era una pregunta interesante, y alguien más podría encontrarse con el mismo problema.

Profano
fuente
-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
fuente