Blog
Proyecto: Reconocimiento facial y alerta por correo electrónico
- Publicado por: Rafael Fernandez
- Categoría: Blog Raspberry Pi
Hacer la implementación de un proyecto real con Raspberry Pi en el que reconoceremos una cara humana y enviaremos un email con la imagen.
En este proyecto vamos a desarrollar una cámara de vigilancia que hace reconocimientos faciales y nos envía un email cada vez que detecta una persona.
¿Como instalar OpenCV en la Raspberry Pi? opción a)
La instalación de Open CV requiere mucho tiempo si tienes una Raspberry Pi 1 Modelo B, ya que opencv es una librería muy completa y con muchas funciones. Para instalar OpenCV en la raspberry Pi sigue los siguientes pasos:
- Para ahorrarnos ese tiempo lo que haremos en este proyecto es descargar la libreria de OpenCV para Raspberry Pi ya compilada desde este link.
- Descomprime el archivo y cambia el nombre de la carpeta a opencv24 (puedes descomprimir en tu pc y o desde la misma raspberry pi).
- Copia o mueve la carpeta al directorio /usr/local/lib/ (mv origen destino: mueve el fichero llamado origen a uno nuevo llamado destino, si no tienes derechos prueba sudo mv origen destino, nosotros lo hemos hecho desde el terminal con ese comando)
- Para que cuando ejecutes alguna función de la librería de opencv y la raspberry pi sepa donde buscar la función, deberás crear el archivo opencv.conf en este directorio /etc/ld.so.conf.d/opencv.conf y ejecutar “sudo ldconfig”
- Una vez realizado estos 4 pasos comprueba con python que si ejecutas “import cv2” no te sale ningun error y la libreria ha sido correctamente instalada.
¿Como instalar OpenCV en la Raspberry Pi? opción b)
Esta opción va dirigida a los usuarios mas expertos o los que tienen una raspberry pi de los últimos modelos ya que toma mas tiempo (en una raspberry antigua puedes tomar 5 horas).
sudo apt-get update sudo apt-get -y dist-upgrade sudo apt-get update sudo apt-get upgrade sudo apt-get purge wolfram-engine sudo apt-get purge libreoffice* sudo apt-get clean sudo apt-get autoremove sudo apt-get install build-essential cmake pkg-config sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev sudo apt-get install libxvidcore-dev libx264-dev sudo apt-get install libgtk2.0-dev libgtk-3-dev sudo apt-get install libatlas-base-dev gfortran sudo apt-get install python3-dev wget https://bootstrap.pypa.io/get-pip.py sudo python3 get-pip.py pip install numpy cd ~/opencv mkdir build cd build cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D INSTALL_C_EXAMPLES=OFF \ -D INSTALL_PYTHON_EXAMPLES=ON \ -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \ -D BUILD_EXAMPLES=ON .. make -j4 sudo make install sudo ldconfig
Ejecuta estas líneas 1 a 1 en el terminal de tu raspberry pi y luego al final comprueba abriendo python que si ejecutas “import cv2” no te sale ningun error, de lo contrario opencv no estará instalado correctamente.
¿Cual es mejor la opcion a) o b)?
Las 2 son igual de buenas. Nosotros hemos usado la a) ya que tenemos un modelo de raspberry pi un poco antiguo.
Una vez tenemos OpenCV instalado podemos empezar a hablar de los códigos que vamos a usar para este proyecto y empezamos por el codigo principal:
import cv2 import config import face import picam import emailer import time import datetime import os import shutil import glob import subprocess # Inicializacion de la camara camera = config.get_camera() while True: # obteniendo la imagen image = camera.read() gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) cv2.equalizeHist(gray_image,gray_image) gray_image = cv2.resize(gray_image,(160,120)) #tiempo t = cv2.getTickCount() # Deteccion cara humana result = face.detect_single(gray_image,config.HAAR_FACES) if result is None: pass else: print ('Cara humana encontrada') x, y, w, h = result cv2.rectangle(image,(x,y),(x+w,y+h),(255,0,0),2) cv2.imwrite(config.DEBUG_IMAGE, image) emailer.sendMail(["XXX@gmail.com"], "Mensaje enviado desde Raspberry pi", "Hemos detectado a alguien", ["capture.jpg"]) t = cv2.getTickCount() - t print ("Tiempo tomado para la deteccion = %gms" % (t/(cv2.getTickFrequency()*1000.)))
Funcionamiento del código principal:
El código está formado por 2 estructuras básicas, un bucle while y una sentencia if. A partir de estas dos estructuras podemos decir que la cámara siempre está en funcionamiento con la estructura while y analizando la imagen que toma con el algoritmo de cascada (algoritmo de reconocimiento que consume pocos recursos) continuamente. La sentencia if entra en juego cuando el algoritmo de cascada detecta una cara humana y entonces es cuando se envía un email con la imagen de la cara humana detectada.
Algoritmo de cascada:
Este algoritmo ya lo hemos usado en el siguiente post Detección de rostros, caras y ojos con Haar Cascad si tienes alguna duda visita el post.
¿Cómo enviar emails con la raspberry pi?
Si te fijas en el código principal en la línea 36 (del código principal) “emailer.sendMail([“XXX@gmail.com”],” se utiliza la función sendMail la cual la podéis ver a continuación y es la que envia el email:
import smtplib from email.MIMEMultipart import MIMEMultipart from email.MIMEBase import MIMEBase from email.MIMEText import MIMEText from email.Utils import COMMASPACE, formatdate from email import Encoders import os USERNAME = "XXX@gmail.com" PASSWORD = "contraseña" def sendMail(to, subject, text, files=[]): assert type(to)==list assert type(files)==list msg = MIMEMultipart() msg['From'] = USERNAME msg['To'] = COMMASPACE.join(to) msg['Date'] = formatdate(localtime=True) msg['Subject'] = subject msg.attach( MIMEText(text) ) for file in files: part = MIMEBase('application', "octet-stream") part.set_payload( open(file,"rb").read() ) Encoders.encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file)) msg.attach(part) server = smtplib.SMTP('smtp.gmail.com:587') server.ehlo_or_helo_if_needed() server.starttls() server.ehlo_or_helo_if_needed() server.login(USERNAME,PASSWORD) server.sendmail(USERNAME, to, msg.as_string()) server.quit()
Otras funciones a comentar del código:
En la línea 27 (del código principal) aparece “detec_single” que es la función que nos dice si hay una cara o no en la imagen. A continuación podéis ver la función:
import cv2 import config def detect_single(image,classifier): haar_faces = cv2.CascadeClassifier(classifier) faces = haar_faces.detectMultiScale(image, scaleFactor=config.HAAR_SCALE_FACTOR, minNeighbors=config.HAAR_MIN_NEIGHBORS, minSize=config.HAAR_MIN_SIZE, flags=cv2.CASCADE_SCALE_IMAGE) if len(faces) != 1: return None return faces[0]
Otra función necesaria es la de “get_camera” en la línea 14 (del código principal) para inicializar la camara y donde se define el archivo de cascada y sus parámetros:
HAAR_FACES = 'haarcascade_frontalface_default.xml' HAAR_SCALE_FACTOR = 1.2 HAAR_MIN_NEIGHBORS = 4 HAAR_MIN_SIZE = (20, 20) DEBUG_IMAGE = 'capture.jpg' def get_camera(): import picam return picam.OpenCVCapture()
Por último tambien hemos definido una clase con el método read el cual es usado en la línea 18 (del código principal). En el metodo read definimos el tamaño de la imagen (320×240), el formato (jpeg) y hacemos una rotación de la imagen:
import io import time import cv2 import numpy as np import picamera import config class OpenCVCapture(object): def read(self): data = io.BytesIO() CAMERA_WIDTH = 320 CAMERA_HEIGHT = 240 with picamera.PiCamera() as camera: camera.resolution = (CAMERA_WIDTH, CAMERA_HEIGHT) camera.rotation = (90) camera.capture(data, format='jpeg') data = np.fromstring(data.getvalue(), dtype=np.uint8) image = cv2.imdecode(data, 1) return image
Si quieres descargar todos los códigos utilizados para este proyecto lo puedes hacer desde aquí reconocimientoyemaildealertaF
Por útimo no te olvides de aceptar desde la cuenta gmail de la cual vallas a enviar el email de alerta el control de la cuenta desde aplicaciones exteriores “poco seguras” ya que vamos a controlar esa cuenta desde la raspberry pi para mandar los emails. Para ello logueate en el gmail y ve a https://myaccount.google.com/security y permite el acceso como en la imagen:
Para alguna duda no olvides escribir un comentario mas abajo!
➡ Aprende mas sobre el manejo, administración y operación de las Raspberry Pi en nuestro Curso de Raspberry Pi:
Buenas Rafael
En primer lugar darte la echo rabieta es un tutoríal muy logrado.
He desarrollado todo y me falla el archivo face.py tal y como lo tienes me indica tiene mal la identacion en particular me obliga a meter el return None dentro del bucle ir y ponerlo a la misma altura que él return faces[0]. Lo ajustó y el script se inicia pero no me detecta caras.
Que podría ser ?
Hola Luis, revisa el código porque yo lo acabo de ejecutar y me funciona correctamente… al principio y depende de la raspberry pi que tengas puede costar un poco que reconozca la cara por eso si no te funciona deberias de tunear un poco el codigo de reconocimiento aunque te debería funcionar sin problemas como está descrito en el tutorial ya que mi raspberry pi es antigua. Saludos y gracias por escribir!
Buenas Rafael,
quiero darte las gracias por este buen tutorial, excelente.
quiero ademas preguntarte como seria para no recocnocer caras sino comparar una fotografia de un elemnto con otras del mismo elento para detectar diferencias o errores.
mil gracias de antemano.
cordialmente
Nelson Rua.
Quiero saber como se hace esto pero que se guarde en firebase
Buenas, funcionaría en vez de un módulo de camara, una camara usb compatible?
Hola Eric, funcionaria perfectamente. Gracias por comentar!
Buenas tardes
Justo estoy realizando un proyecto de reconocimiento facial con raspberry pi, y ya he instalado opencv, pero cuando veo lo del código, tengo dudas, abro un archivo y pego el código principal, y los otros códigos donde los meto, estoy un poco perdido.
Muchas gracias.
Buenas Tardes, Tengo unas Raspberry Pi 4, con una Micro SD 64GB, con este Hardware podría hacer una reconocimiento facial para una portería de una fabrica con mas de 1800 personas? GRACIAS.
Hola Eric, yo creo que tienes hardware de sobra para reconocer a 1800 personas si tienes un código optimizado. Saludos!
Buenas noches muy buen tutorial soy estudiante y me gustaria saber como puedo insertar en una base de datos mysql el nombre, la fecha y hora en la que la cámara detecta a una persona y la reconozca; cual seria la función que permitirá hacer esa parte.
GRACIAS
Muy buenos dias
cuando yo corro el codigo en mi raspberry me sale un error en las partes en la que se importa algo.
por favor me pueden ayudar??