python - landmarks - ¿Cómo realizar la detección estable de la esquina del ojo?
opencv landmark detection python (3)
Para aquellos que lo encuentran demasiado largo, solo lea las líneas en negrita.
Mi proyecto de estimación de la mirada basada en el cursor de la pantalla que se mueve en el HCI ahora depende de una última cosa: la estimación de la mirada, para lo cual estoy utilizando las esquinas de los ojos como un punto estable de referencia respecto del cual detectaré el movimiento de la pupila y calcularé la mirada.
Pero no he podido detectar de manera estable las esquinas de los ojos de la transmisión de webcam en vivo. He estado usando las funciones cv.CornerHarris () y GFTT - cv.GoodFeaturesToTrack () para la detección de esquinas. Probé la demo FAST (el ejecutable de su sitio web) directamente en las imágenes de mis ojos, pero eso no fue bueno.
Estos son algunos resultados de mis detecciones de esquinas hasta ahora para imágenes.
Utilizando GFTT:
Usando Harris:
que pasa en el video
Los círculos verdes son las esquinas, los otros (en rosa, círculos más pequeños) son las otras esquinas
Utilicé una cierta heurística: las esquinas estarán en los extremos izquierdo y derecho y alrededor de la mitad si se piensa verticalmente. Lo he hecho porque después de tomar muchas instantáneas en muchas condiciones, a excepción de menos del 5% de las imágenes, el descanso es como este, y para ellas lo son las heurísticas anteriores.
Pero estas detecciones de esquinas son para instantáneas, no de la alimentación de la cámara web.
Cuando uso metodologías (harris y GFTT) para la transmisión de la cámara web, simplemente no las consigo.
Mi código para la detección de esquinas usando cv.CornerHarris
Esquinas de los ojos usando GFTT
Ahora los parámetros que utilizo en ambos métodos, no muestran resultados para diferentes condiciones de iluminación y, obviamente,. Pero en la misma condición de iluminación en la que se tomaron estas instantáneas, todavía no obtengo el resultado de los cuadros que consulté en el video de la cámara web.
Estos parámetros de GFTT funcionan bien para condiciones de iluminación promedio
cornerCount = 100
qualityLevel = 0.1
minDistance = 5
mientras que estos:
cornerCount = 500
qualityLevel = 0.005
minDistance = 30
funcionó bien para la imagen estática mostrada arriba
MinDistance = 30 porque obviamente las esquinas tendrían al menos esa distancia, de nuevo, algo de una tendencia que vi en mis fotos. Pero lo bajé para la versión de GFTT de la fuente de la cámara web porque entonces no estaba obteniendo ninguna curva.
Además, para la versión de transmisión en vivo de GFTT, hay un pequeño cambio que tuve que acomodar:
cv.CreateImage((colorImage.width, colorImage.height), 8,1)
mientras que para la versión de imagen fija (código en pastebin) usé:
cv.CreateImage(cv.GetSize(grayImage), cv.IPL_DEPTH_32F, 1)
Presta atención a las profundidades.
¿Cambiaría eso alguna cualidad de detección?
La imagen del ojo que estaba pasando el método GFTT no tenía una profundidad de 32F, así que tuve que cambiarlo y de acuerdo con el resto de las imágenes temporales (eignenimg, tempimg, etc.)
En conclusión: tengo que terminar la estimación de la mirada, pero sin la detección estable de la esquina de los ojos no puedo progresar ... y debo continuar con la detección de parpadeo y el seguimiento de alumnos basado en la coincidencia de plantillas (¿o sabe qué?). En pocas palabras, quiero saber si estoy cometiendo errores de novato o no haciendo cosas que me impiden obtener la detección de esquina de ojo casi perfecta en el flujo de video de mi cámara web, que obtuve en mis instantáneas que publiqué aquí.
De todos modos gracias por darle una vista a esto. Cualquier idea de cómo podría realizar la detección de esquinas de ojos para varias condiciones de iluminación sería muy útil
De acuerdo, si no obtuviste lo que estoy haciendo en mi código (cómo obtengo las esquinas izquierda y derecha), te explicaré:
max_dist = 0
maxL = 20
maxR = 0
lc =0
rc =0
maxLP =(0,0)
maxRP =(0,0)
for point in cornerMem:
center = int(point[0]), int(point[1])
x = point[0]
y = point[1]
if ( x<colorImage.width/5 or x>((colorImage.width/4)*3) ) and (y>40 and y<70):
#cv.Circle(image,(x,y),2,cv.RGB(155, 0, 25))
if maxL > x:
maxL = x
maxLP = center
if maxR < x:
maxR = x
maxRP = center
dist = maxR-maxL
if max_dist<dist:
max_dist = maxR-maxL
lc = maxLP
rc = maxRP
cv.Circle(colorImage, (center), 1, (200,100,255)) #for every corner
cv.Circle(colorImage,maxLP,3,cv.RGB(0, 255, 0)) # for left eye corner
cv.Circle(colorImage,maxRP,3,cv.RGB(0,255,0)) # for right eye corner
maxLP y maxRP almacenarán (x, y) para las esquinas izquierda y derecha del ojo, respectivamente. Lo que estoy haciendo aquí es tomar una variable para la detección de esquinas izquierda y derecha, maxL y maxR respectivamente, que se comparará con los valores de x de las esquinas detectadas. Ahora simplemente, para maxL, tiene que ser algo más que 0; Le asigné 20 porque si la esquina izquierda está en (x, y) donde x <20, entonces maxL será = x, o si dice, es decir, la ordenada X de la esquina izquierda se encuentra de esta manera. Del mismo modo para la esquina más derecha.
También intenté con maxL = 50 (pero eso significaría que la esquina izquierda está casi en el centro de la región del ojo) para obtener más candidatos para la transmisión de la cámara web, en la que no obtengo ninguna esquina.
Además, max_dist almacena la distancia máxima entre las ordenadas X vistas hasta ahora, y por lo tanto da una medida de qué par de esquinas serían las esquinas del ojo izquierdo y derecho, la que tiene la distancia máxima = max_dist
Además, he visto en mis instantáneas que las ordenadas Y de las esquinas de los ojos caen entre 40 y 70, así que también utilicé eso para minimizar el grupo de candidatos
¿Has probado la segmentación de la esclerótica?
Es posible que también pueda hacer con las 2 esquinas de la esclerótica, y esto podría ser más fácil porque ya tiene una detección de pupila decente funcionando, la esclerótica es la región más brillante que rodea a la pupila.
Creo que hay una manera fácil de ayudar!
Parece que estás considerando cada ojo aislado. Lo que sugiero que hagas es combinar tus datos para ambos ojos y también usar geometría facial. Ilustraré mis sugerencias con una imagen que algunas personas pueden reconocer (no es realmente el mejor ejemplo, ya que es una pintura, y su cara está un poco descentrada, pero ciertamente es la más divertida ...)
Parece que tiene estimaciones confiables para la posición de la pupila para ambos ojos, y dado que la cara se ve bastante recta a la cámara (las rotaciones faciales perpendiculares a la pantalla estarán bien con este método), sabemos que las esquinas de los ojos ( de ahora en adelante, solo ''esquinas'') estarán en (o cerca de) la línea que pasa por las pupilas de ambos ojos (línea roja punteada).
Sabemos la distancia entre los alumnos, a
, y sabemos que la relación entre esta distancia y la distancia a través de un ojo (esquina con esquina), b
, es fija para un individuo y no cambiará mucho en la población adulta ( puede diferir entre sexos).
ie. a / b = constant.
Por lo tanto podemos deducir b, independientemente de la distancia de los sujetos de la cámara, conociendo solo a
.
Usando esta información podemos construir cuadros de umbrales para cada esquina de ojo (cuadros punteados, en detalle, etiquetados 1, 2, 3, 4
). Cada caja es b
por c
(altura del ojo, nuevamente determinable a través del mismo principio de proporción fija) y se encuentra paralela al eje de la pupila. El borde central de cada caja se fija al centro de la pupila y se mueve con ella. ¡Sabemos que cada esquina siempre estará en su propio cuadro de umbral!
Ahora, por supuesto, el problema es que los alumnos se mueven, y también lo hacen nuestros recuadros de umbrales ... pero hemos reducido el campo de forma masiva de esta manera, porque podemos descartar con confianza TODAS las posiciones de los ojos estimadas (de Harris o GFTT o cualquier otra cosa) caer fuera de estas casillas (siempre que tengamos confianza en la detección de nuestros alumnos).
Si tenemos una alta confianza en una sola posición de esquina, podemos extrapolar y deducir todas las otras posiciones de esquina solo desde la geometría. (para ambos ojos!).
Si hay dudas entre las múltiples posiciones de las esquinas, podemos usar el conocimiento de otras esquinas (de cualquiera de los dos ojos) para resolverlo vinculando probabilísticamente sus posiciones, haciendo una mejor estimación. es decir. cualquier par de estimaciones (dentro de sus casillas, por supuesto) se encuentran separadas y paralelas al eje de la pupila.
- Si puede obtener posiciones generales de "ojo" que no se mueven cuando la pupila se mueve (o de hecho, cualquier característica facial en el mismo plano), esto es muy útil y le permite determinar las posiciones de las esquinas geométricamente.
Espero que esto pueda ayudarlo a encontrar la d
elusiva (desplazamiento de la pupila desde el centro del ojo).
cambié esto
if ( x<colorImage.width/5 or x>((colorImage.width/4)*3) ) and (y>40 and y<70):
a esto:
if ( x<(w/5) or x>((w/4)*3) ) and (y>int(h*0.45) and y<int(h*0.65)):
porque antes, solo estaba mirando manualmente los valores de píxeles más allá de los cuales se encuentran mis ventanas donde se podían encontrar esquinas con la mayor probabilidad. Pero luego, luego me di cuenta, vamos a hacerlo general, así que hice una ventana horizontal de 45 a 65 pc del rango Y, y de 1 / 5th a 3 / 4ths para el rango X, porque esa es el área usual dentro de la cual están las esquinas.
Lo siento, muchachos por responder tarde, estaba ocupado con la última parte del proyecto: estimación de la mirada. Y voy a publicar una pregunta al respecto, estoy atrapado en eso.
por cierto, aquí hay algunas imágenes de esquinas de ojos y pupilas detectadas en mi ojo: (agrandada a 100x100)
Espero que esto sea útil para otros que comienzan en esta área.