No se pueden detectar puntos de referencia faciales usando OpenCV2
He desarrollado un guión usando dlib
y cv2
para dibujar puntos de referencia faciales en imágenes que tienen una cara en esa imagen. Aquí están los guiones;
import cv2
import dlib
img_path = 'landmarks.png'
detector = dlib.get_frontal_face_detector()
shape_predictor = 'shape_predictor_68_face_landmarks.dat'
predictor = dlib.shape_predictor(shape_predictor)
count = 1
ready = True
while ready:
frame = cv2.imread("demo.jpg")
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = detector(gray)
for face in faces:
x1 = face.left()
y1 = face.top()
x2 = face.right()
y2 = face.bottom()
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 3)
landmarks = predictor(gray, face)
for n in range(0, 68):
x = landmarks.part(n).x
y = landmarks.part(n).y
cv2.circle(frame, (x, y), 4, (255, 0, 0), -1)
cv2.imshow("Frame", frame)
cv2.waitKey(0)
ready = False
Ahora, aquí lo que me vuelve loco. Cuando intento descargar cualquiera de las imágenes (con o sin máscara) de Google para probarlo, este script funciona bien. Asimismo, puede ver estos resultados como,
Pero cuando pruebo estas imágenes siguientes, no hace nada.
He realizado un par de búsquedas en Internet, pero no he encontrado nada que sirva para el propósito actual.
Incluso, he probado la combinación de
cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
m_cascade = cv2.CascadeClassifier('haarcascade_mcs_mouth.xml')
También he examinado los siguientes enlaces útiles que existen;
Caja delimitadora de caras
Detectar marcas faciales en Android (incluso no en el mismo dominio)
Detección de puntos de referencia
OpenCV2 Detecta marcas faciales
pero tampoco funciona con estas imágenes. CV2 detector
muestra una lista vacía cuando depuro a través de un script como;
Solo quiero dibujar puntos de referencia fiduciales usando las imágenes de arriba. ¿Cuál sería la mejor solución posible por la que puedo pasar? Tal vez, me falta algo en cv2
& Dlib
, pero no puedo obtener los resultados requeridos.
También encontré el puntaje de confianza para dlib
usar la implementación recomendada de un geek de Stack Overflow como;
import dlib
detector = dlib.get_frontal_face_detector()
img = dlib.load_rgb_image('demo.jpg')
dets, scores, idx = detector.run(img, 1, -1)
for i, d in enumerate(dets):
print("Detection {}, score: {}, face_type:{}".format(
d, scores[i], idx[i]))
Aquí está el resultado de una puntuación de confianza para la primera imagen en las imágenes dadas arriba en la segunda fila;
Espero obtener una mejor investigación de cualquiera de los chicos geniales que hay. Gracias
Respuestas
Primero, podría intentar ver si puede obtener puntajes de confianza de dlib. No estoy seguro de cuál es el umbral de confianza, pero tal vez se detecten rostros que están por debajo del límite. Del dlib Git Repo , aquí hay un ejemplo de cómo obtener confianza de las detecciones:
if (len(sys.argv[1:]) > 0):
img = dlib.load_rgb_image(sys.argv[1])
dets, scores, idx = detector.run(img, 1, -1)
for i, d in enumerate(dets):
print("Detection {}, score: {}, face_type:{}".format(
d, scores[i], idx[i]))
Alternativamente, considere otro detector facial, por ejemplo, un detector basado en CNN como este detector facial MobileNet SSD . No he usado este modelo en particular, pero he usado modelos similares, como el modelo de detector facial basado en TPU de Google aquí con muy buenos resultados.
Descargar el enlace " shape_predictor_68_face_landmarks.dat ": introduzca la descripción del enlace aquí
Código 100% funcional Prueba este:
import cv2
import dlib
import numpy as np
img= cv2.imread('Capture 8.PNG')
gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
p = "shape_predictor_68_face_landmarks.dat"
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(p)
faces = detector(gray)
for face in faces:
x1=face.left()
y1=face.top()
x2=face.right()
y2=face.bottom()
cv2.rectangle(img, (x1,y1), (x2,y2),(0,255,0),3)
landmarks=predictor(gray, face)
for n in range(0,68):
x=landmarks.part(n).x
y=landmarks.part(n).y
cv2.circle(img, (x, y), 4, (0, 0, 255), -1)
cv2.imshow(img)