detecção básica da pele hsb, iluminação neon


14

Espero que este seja o lugar certo para perguntar. caso contrário, desculpe-me pelo meu erro e peça-me um site melhor.

Eu estou tentando implementar um detector de pele super simples usando alguma variedade de imagem hsb. Estou usando a abordagem descrita aqui e aqui .

Estou tentando usar uma fonte de vídeo da minha webcam. se eu usar iluminação solar, funciona muito bem (não é tão bom, mas é muito bom), mas com luz neon ... é uma bagunça. muita região branca é detectada e muito barulho em todos os lugares.

porque?

Estou usando o algoritmo descrito na segunda fonte :

  1. converter imagem ho espaço de cores HSV
  2. coloque branco no intervalo 0 <H <38
  3. filtro dilatado
  4. corroer filtro
  5. filtro de desfoque

insira a descrição da imagem aqui

Respostas:


10

Na verdade, isso pode funcionar melhor usando um modelo generativo simples em RGB, em vez de HSV.

  1. Obtenha uma imagem de treinamento ou várias imagens de treinamento com um pouco de pele.
  2. Selecione manualmente os pixels da capa (por exemplo, criando uma máscara binária)
  3. Calcular a média e a covariância do tom de pele em RGB (cada um deve ser vetores de 3 elementos)
  4. Para um pixel desconhecido, calcule sua distância de Mahalanobis a partir da média, usando a covariância.
  5. Classifique-o como skin se a distância for menor que um limite.
  6. Ajuste o limite para obter o melhor desempenho.

Edit: Não sei se o OpenCV tem uma função para calcular a covariância, mas posso lhe dizer como fazer isso sozinho. Digamos que você tenha pixels RGB. Você colocá-los em um n x 3 matriz, vamos chamá-lo P . Em seguida, calcule m , que é o vetor RGB médio, calculando a média das colunas. m será um vetor 1 x 3. Subtrair m a partir de cada linha de P e chamar a matriz resultante Q . Agora a covariância de computação, tudo que você tem a fazer é multiplicar Q pela transposta de si: C = Q ' Q . Certifique-se de que CnnPmmmPQQC=QQC é 3 x 3.

Edit2: Os valores que você está recebendo parecem muito grandes. Para obter a covariância máxima, crie a seguinte matriz:

255 255 255
 0   0   0

e calcular a covariância disso. Você deve obter uma matriz em que cada valor seja aproximadamente 32513. Portanto, verifique se os valores de pixel variam de 0 a 255 e copie-os em flutuadores ou dobre corretamente. A distância de Mahalanobis está nas unidades de variação, de modo que os números devem ser pequenos. Seu limite para a classificação da pele provavelmente deve ser menor que 4.


Eu tenho problema em entender como obter matriz de covariância 3x3 com opencv a partir de uma imagem .. você pode me dar alguma referência?
Nkint

@ nkint, veja a resposta editada.
Dima

OK ótimo. em 5 linhas, você me fez entender o que é covariância. obrigado. funciona. mas eu tenho problema em armazenar resultados. se eu tenho pixels de 0 a 255, que tipo de números devo esperar da distância de Mahalanobis? se eu armazená-los em um 8-uint ele não ter apenas uma pequena parte da pele, se eu armazená-los em um 32-flutuar eu recebo ruído branco strang
nkint

Sim, acho que estou fazendo algo errado, porque minha matriz de covariância é: [10913058.00000000, 7046611.50000000, 3290781.50000000; 7046611.50000000, 4811646.00000000, 2225078.00000000; 3290781.50000000, 2225078.00000000, 1387631.87500000]
nkint

1
Você pode pensar na covariância como definindo um elipsóide em 3D. Você pode visualizá-lo no Matlab, mas é provável que dê muito trabalho. Como alternativa, você pode tentar olhar para as projeções 2D do elipsóide, mas isso também exigiria algum trabalho.
Dima

4

Leve em consideração os diferentes valores obtidos na cor HSV quando a luz de neon for aplicada: um exemplo de seu desvio está aqui . Tente adaptar seu algoritmo para que ele se adapte a esses valores.

Aqui existe outro algoritmo para detectar a pele e, para detectar condições de luz, você pode usar este .

Outro algoritmo, relacionado à detecção da pele, mas não muito relacionado aos efeitos da luz neon, é esse .


2

As respostas que você obteve até agora apontam para bons métodos alternativos, mas se você estiver interessado em usar algo como o algoritmo inicial, provavelmente não é difícil de corrigir. Você só precisa ajustar as peculiaridades do HSV do OpenCV. Dados os resultados malucos, presumo que você provavelmente tenha usado uma das representações numéricas mais comuns do HSV na escolha de seus limites e / ou na conversão de pixels?

O OpenCV representa o HSV de maneira diferente da maioria das outras fontes que você pode ter encontrado:

  • A maior diferença para você seria com matiz w / r / t: o OpenCV representa o matiz variando de 0 a 179, quando quase todo o resto aproveita o bit pendente para preservar mais informações, com 0-255.
  • A outra diferença: a medição da saturação é invertida em comparação com a norma. Então 255 saturação significa brilhante em opencv, em vez de branco (observe, estamos de volta a 255 - apenas o tom é de 0 a 180, talvez por causa da representação da 'roda'?)

Provavelmente tarde demais para ajudá-lo, mas era uma pergunta interessante, e outra pessoa poderia ter o mesmo 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)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.