Resolviendo algunas dudas del video anterior ( Reconocimiento facial con OpenCV y Python )
Te doy la bienvenida a un nuevo post. Esta vez estaré resolviendo algunas dudas que me han hecho llegar sobre el tutorial anterior: ? Reconocimiento Facial ? | Python – OpenCV
CONTENIDO
- ¿Entrené con CPU o GPU?
- ¿Cuánto tiempo se tardó en entrenar cada reconocedor?
- ¿Cómo se desempeña cada reconocedor?
- ¿Y para qué me sirven estos datos?
- ¿Con estos métodos (EigenFaces, FisherFaces y LBPH) se puede reconocer a más de una persona que aparezca en una imagen?
¿Entrené con CPU o GPU?
Para entrenar el reconocedor de rostros tanto con EigenFaces, FisherFaces y LBPH que vimos en el anterior tutorial lo entrené con CPU.
¿Cuánto tiempo se tardó en entrenar cada reconocedor?
Anteriormente habíamos entrenado reconocedores faciales para poder identificar a dos personas: Brenda y Gaby. Para el entrenamiento se contó con 300 imágenes de 150 x 150 pixeles con los rostros de cada una.
Para obtener el tiempo de duración por cada entrenamiento voy a incrementar unas cuantas líneas en el código anteriormente usado, veamos:
import cv2 import os import numpy as np import time dataPath = 'C:/Users/Gaby/Desktop/Reconocimiento Facial/Data' #Cambia a la ruta donde hayas almacenado Data peopleList = os.listdir(dataPath) print('Lista de personas: ', peopleList) labels = [] facesData = [] label = 0 for nameDir in peopleList: personPath = dataPath + '/' + nameDir #print('Leyendo las imágenes') for fileName in os.listdir(personPath): #print('Rostros: ', nameDir + '/' + fileName) labels.append(label) facesData.append(cv2.imread(personPath+'/'+fileName,0)) #image = cv2.imread(personPath+'/'+fileName,0) #cv2.imshow('image',image) #cv2.waitKey(10) label = label + 1 #print('labels= ',labels) print('Número de etiquetas 0: ',np.count_nonzero(np.array(labels)==0)) print('Número de etiquetas 1: ',np.count_nonzero(np.array(labels)==1)) # Métodos para entrenar el reconocedor face_recognizer = cv2.face.EigenFaceRecognizer_create() #face_recognizer = cv2.face.FisherFaceRecognizer_create() #face_recognizer = cv2.face.LBPHFaceRecognizer_create() # Entrenando el reconocedor de rostros print("Entrenando...") inicio = time.time() face_recognizer.train(facesData, np.array(labels)) tiempoEntrenamiento = time.time()-inicio print("Tiempo de entrenamiento: ", tiempoEntrenamiento) # Almacenando el modelo obtenido face_recognizer.write('modeloEigenFace.xml') #face_recognizer.write('modeloFisherFace.xml') #face_recognizer.write('modeloLBPHFace.xml') print("Modelo almacenado...")
Línea 4: Importamos time
.
Línea 38: Tomamos el tiempo actual que se almacenará en inicio
.
Línea 40: Restamos el tiempo actual menos el tiempo en inicio
que se almacenará en tiempoEntrenamiento
. Recuerda que para poder monitorear el tiempo trascurrido debes tomar el tiempo anterior y posterior al de la línea 39 que corresponde al entrenamiento.
Línea 41: Visualizamos el tiempo transcurrido en segundos.
Ahora que ya tenemos como conocer el tiempo de entrenamiento vamos a experimentar en dos escenarios (computadores), con cada uno de los métodos: eigenFaces, fisherFaces, LBPH. Veamos:
¿Cómo se desempeña cada reconocedor?
Esta es una pregunta que me la he plateado yo, ya que quisiera mostrarte como está trabajando cada reconocedor con cada método entrenado. Esta vez voy a evaluar cuanto tiempo le toma la ejecución de un video aplicando el reconocimiento, además su fps (frame rate / fotogramas por segundo).
Para ello estaré usando la librería imutils
, que nos ayudará a calcular el tiempo estimado de reproducción, además de los fps.
import cv2 import os from imutils.video import FPS dataPath = 'C:/Users/Gaby/Desktop/Reconocimiento Facial/Data' #Cambia a la ruta donde hayas almacenado Data imagePaths = os.listdir(dataPath) print('imagePaths=',imagePaths) #face_recognizer = cv2.face.EigenFaceRecognizer_create() #face_recognizer = cv2.face.FisherFaceRecognizer_create() face_recognizer = cv2.face.LBPHFaceRecognizer_create() # Leyendo el modelo #face_recognizer.read('modeloEigenFace.xml') #face_recognizer.read('modeloFisherFace.xml') face_recognizer.read('modeloLBPHFace.xml') #cap = cv2.VideoCapture(0,cv2.CAP_DSHOW) cap = cv2.VideoCapture('Imagenes y Videos de Prueba/GabyTest1.mp4') faceClassif = cv2.CascadeClassifier(cv2.data.haarcascades+'haarcascade_frontalface_default.xml')
fps = FPS().start() while True: ret,frame = cap.read() if ret == False: break gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) auxFrame = gray.copy() faces = faceClassif.detectMultiScale(gray,1.3,5) for (x,y,w,h) in faces: rostro = auxFrame[y:y+h,x:x+w] rostro = cv2.resize(rostro,(150,150),interpolation= cv2.INTER_CUBIC) result = face_recognizer.predict(rostro) cv2.putText(frame,'{}'.format(result),(x,y-5),1,1.3,(255,255,0),1,cv2.LINE_AA) ''' # EigenFaces if result[1] < 5700: cv2.putText(frame,'{}'.format(imagePaths[result[0]]),(x,y-25),2,1.1,(0,255,0),1,cv2.LINE_AA) cv2.rectangle(frame, (x,y),(x+w,y+h),(0,255,0),2) else: cv2.putText(frame,'Desconocido',(x,y-20),2,0.8,(0,0,255),1,cv2.LINE_AA) cv2.rectangle(frame, (x,y),(x+w,y+h),(0,0,255),2) # FisherFace if result[1] < 500: cv2.putText(frame,'{}'.format(imagePaths[result[0]]),(x,y-25),2,1.1,(0,255,0),1,cv2.LINE_AA) cv2.rectangle(frame, (x,y),(x+w,y+h),(0,255,0),2) else: cv2.putText(frame,'Desconocido',(x,y-20),2,0.8,(0,0,255),1,cv2.LINE_AA) cv2.rectangle(frame, (x,y),(x+w,y+h),(0,0,255),2) ''' # LBPHFace if result[1] < 70: cv2.putText(frame,'{}'.format(imagePaths[result[0]]),(x,y-25),2,1.1,(0,255,0),1,cv2.LINE_AA) cv2.rectangle(frame, (x,y),(x+w,y+h),(0,255,0),2) else: cv2.putText(frame,'Desconocido',(x,y-20),2,0.8,(0,0,255),1,cv2.LINE_AA) cv2.rectangle(frame, (x,y),(x+w,y+h),(0,0,255),2) cv2.imshow('frame',frame) k = cv2.waitKey(1) if k == 27: break fps.update() fps.stop() print("Tiempo de reproducción: {:.2f}".format(fps.elapsed())) print("FPS aproximado: {:.2f}".format(fps.fps())) cap.release() cv2.destroyAllWindows()
Línea 3: Con from imutils.video import FPS
, importamos lo necesario para obtener el tiempo de reproducción y su fps asociado.
Línea 22: Necesitamos iniciar con el proceso con FPS().start()
, previo a la lectura del video.
Línea 67: Luego de la lectura de cada fotograma digitados fps.update()
, para que cuente cada iteración y al final pueda calcular el fps.
Línea 69: Una vez que el video haya finalizado digitamos fps.stop()
.
Línea 70 y 71: Vamos a visualizar el tiempo de reproducción (fps.elapsed()
), y el fps aproximado (fps.fps()
).
Para probar este código usé un video de 8 segundos de duración, a 20 fotogramas por segundo (puedes verlo aquí).
Apliqué la programación a este video en un computador intel core i5, intel core i7 y además con una raspberry pi 3B. Estos fueron los resultados:
¿Y para qué me sirven estos datos?
El video de entrada tiene 8 segundos de duración y fps de 20. Sería «lógico» pensar que OpenCV va a respetar estos datos y mostrarnos una salida idéntica al video de entrada sin embargo, lo cierto es que OpenCV busca realizar los procesos u operaciones lo más rápido posible, es por ello que cuando simplemente visualizamos un video, este se muestra a gran velocidad.
Entonces, el resultado de aplicar reconocimiento facial con cada uno de estos métodos (EigenFaces, FisherFaces y LBPH) cambiará dependiendo de cada uno de ellos, dadas las operaciones que conlleva usarlos.
Si consideramos por ejemplo las mediciones realizadas para un computador con core i5 y 6GB de RAM, en EigenFaces tenemos un fps 9.54, con FisherFaces 24.08 y LBPH 8.92. Para el ejemplo que estamos tomando, el fps que más se acercaría al del video de entrada es el de LBPH, mientras que el más alto sería el correspondiente a FisherFaces. Comparando estos dos valores podemos darnos cuenta de que con FisherFaces tenemos más rapidez en las operaciones que realiza el reconocedor para identificar a una persona (dado que analiza rápidamente cada fotograma a comparación con el otro método), mientas que con LBPH es más tardado, por lo tanto se puede apreciar que este último es más costoso computacionalmente.
Cabe destacar que esta comparación la he realizado con el objetivo de analizar cual de estos métodos es más costoso computacionalmente, dado el ejemplo que he tomado, mas no para determinar que tan bien o mal está reconociendo a la persona.
¿Con estos métodos (EigenFaces, FisherFaces y LBPH) se puede reconocer a más de una persona que aparezca en una imagen?
El proceso de reconocimiento se da luego de la detección facial, por tanto todo rostro detectado pasará por el proceso de reconocimiento para ser etiquetado con el nombre de una persona o como desconocido. Por consiguiente el reconocimiento facial se aplicará a todos los rostros detectados en la imagen.
Veamos un ejemplo de como más de una persona es reconocida:
Hemos llegado al final del post, espero sea útil y que me haya dado entender de mejor manera. Ten un excelente día y nos vemos en el siguiente video/post.
Hola, podría ser aplicado a AWS deeplens?
Hola Roni, disculpa no lo he probado.
hola, podras explicarlo como entrenarlo en una GPU?
Hola Roger, muchas gracias por la sugerencia. 🙂
Mi maestro me recomendó tu pagina, estoy trabajando en un proyecto y lo que mencionas es mucho contenido para lo que quiero realizar, son muy buenos aportes, yo voy a ocupar expresiones, pero ya vi que tienes otro video al respecto. Felicitarte por tu canal y tus grandes aportes.
Hola Mariano, ¿de verdad un maestro tuyo te recomendó mi blog? Wow, muchísimas gracias por dejármelo saber. Me llena de alegría saber que el contenido es de utilidad, espero que te vaya muy bien el proyecto. ¡Muchos éxitos!
Hola buenas Gaby me encanta tus vídeos, estoy aprendiendo en este mundo de OpenCV y me encanto conocer un canal en español como el tuyo mi duda es esta
me sale el siguiente error en el primer método y la verdad no e podido salir de esta.
face_recognizer = cv2.face.EigenFaceRecognizer_create()
AttributeError: module ‘cv2.cv2’ has no attribute ‘face’
crees que me puedas ayudar? porque ya hice de todo instalar el opencv tambien trate con
pip install opencv-contrib-python pero nada el mismo error.
agradeceria muchisimo tu ayuda
Hola Fernando, muchas gracias. Parece que es un problema con la versión de OpenCV que se está usando. Para el reconocimiento facial usé la versión 4.2.
Buena tarde Gaby, gracias por el contenido de tus videos, tengo una duda respecto a ¿Cuáles son las características de la video cámara que utilizas ?, Quiero hacer pruebas pero no se que video cámara comprar, gracias de antemano por tu respuesta, saludos.
Tuve el mismo problema y lo resolví en windows con:
pip install opencv-contrib-python
Intente actualizar su opencv con «python -m pip install opencv-contrib-python» pd: debe eliminar el repositorio CV2 del representante de Python y luego ejecutar este comando (en las ventanas de CMD) si no funciona
hola primeramente muchas gracias por tu aporte, nos ayuda mucho.
mi pregunta es como puedo hacer para que la carpeta ya entrenada no se vuelva a entrenar y solo haga el entrenamiento con las nuevas carpetas.
Hola Edward, el clasificador consigue los resultados de todas las imágenes de entrada. Según mi percepción, tendrías que volver a entrenarlo con todas las imágenes de entrada.
hola Gaby buenos días primero que nada agradecer por aportar con tus conocimientos, ayuda mucho.
Mi pregunta es, como puedo hacer que en el momento de entrenamiento solo entrene los archivos que no están entrenado,
así optimizar el tiempo de entrenamiento.
Hola! de donde obtienes «modeloLBPHFace.xml»?
Hola Jorge, aquí puedes encontrar el procedimiento para obtenerlo: http://omes-va.com/reconocimiento-facial-python-opencv/
como puedo instalar imutils para subliem text en windows 10
Hola Alberto, lo puedes hacer en el símbolo del sistema, allí digitas: pip install imutils
Hola, muy entretenido el tutorial aunque he tenido que pelear con él por errores con versiones de diferentes módulos.
En el último tramo me está lanzando un error que no consigo solucionar:
Script «reconocimientoFacial.py»
Linea:
cv2.putText(frame,'{}’.format(imagePaths[result[0]]),(x,y-25),2,1.1,(0,255,0),1,cv2.LINE_AA)
IndexError: list index out of range
Hola Carlos, al parecer el índice está fuera del rango. Puedes imprimir result[0] a ver que valores obtienes en ese índice, o result.
Hola Gaby, esperando que estés muy bien, quería hacerte una consulta, lo que pasa es que estuve probando el código y me aparece un error, el cual es :
cv2.error: OpenCV(4.5.4) D:\a\opencv-python\opencv-python\opencv\modules\core\src\lda.cpp:1087: error: (-5:Bad argument) At least two classes are needed to perform a LDA. Reason: Only one class was given! in function ‘cv::LDA::lda’
He estado buscando pero no he encontrado una solución, sabes que puede ser?
Me han servido mucho tus videos para algunos proyectos que he hecho, tu pagina es realmente útil para muchas personas, espero puedas ayudarme con este tema.
Buenas tardes, ¿Cómo podría hacer el reconocimiento facial a partir de una imagen ?
Hola, muchas gracias estoy haciendo un proyecto de reconocimiento facial y tu video me ayudo mucho, pero no has hecho un video para utilizar la gpu con un intel i7
Hola me da problemas esta linea, lo demas va correcto:
face_recognizer.train(facesData, np.array(labels))
este error:
error: OpenCV(4.6.0) D:\a\opencv-python\opencv-python\opencv\modules\core\src\matrix.cpp:246: error: (-215:Assertion failed) s >= 0 in function ‘cv::setSize’
No encuentro solucion, ya que el array esta tal cual
Hola Daniel, muy probablemente estés almacenando las imágenes junto con otros tipos de archivo, o por alguna razón las imágenes no se leen de forma correcta.
Verifica que en la carpeta donde indiques que están las imágenes, sólo haya imágenes, y que por supuesto no haya problemas
para leerlas.
Un saludo.
Hola, al igual que al usuario «Braulio Valdés», tambien a mi me sale el mismo error, solo que yo estoy usando la versión de openCV 4.7. :
La línea que origina el error es:
reconocedor = cv2.face.FisherFaceRecognizer_create()
reconocedor.train(datosCaras, np.array(etiquetas)) # Linea que hace saltar el error.
cv2.error: OpenCV(4.7.0) /io/opencv/modules/core/src/lda.cpp:1087: error: (-5:Bad argument) At least two classes are needed to perform a LDA. Reason: Only one class was given! in function ‘lda’
Debo decir que usando el mismo formato de instrucción (como en el ejemplo), tanto el modelo Eigenface, como el modelo LBPH, funcionaron sin problema, solo surge el problema con el modelo Fisherface.
He leído algo sobre como trabaja Fisherface y a parte de trabajar sobre un estandar PCA o Principal component analysis (como Eigenface), tambien lo complementa con otro llamado LDA o Linear discriminant analysis, (el cual, según leo en el error, es el que provoca la rotura).
¿Puede alguien subsanar el origen del error?.
Gracias anticipadas.
el problema radica en que debes tener 2 clases diferentes, en el ejemplo sale brenda y gaby, el algoritmo lda trabaja con mas de una para hacer la clasificacion
Se me presenta el mismo problema y estoy usando la ultima version File «/home/augusto/Escritorio/neuronas/entrenamientoRF.py», line 28, in
face_recognizer.train(facesData, np.array(labels))
cv2.error: OpenCV(4.9.0) /io/opencv/modules/core/src/lda.cpp:1087: error: (-5:Bad argument) At least two classes are needed to perform a LDA. Reason: Only one class was given! in functio