-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit c12b386
Showing
550 changed files
with
165,155 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
*.pb filter=lfs diff=lfs merge=lfs -text | ||
models/*/*.pb filter=lfs diff=lfs merge=lfs -text | ||
*.ckpt.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
__pycache__ | ||
|
||
# No queremos subir lo que generamos ni lo que añadimos en las entradas | ||
outputImages | ||
detectedFaces.avi | ||
images | ||
videos |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
FROM python:3.7 | ||
WORKDIR /code | ||
COPY requirements.txt requirements.txt | ||
RUN pip3 install -r requirements.txt | ||
COPY . . | ||
CMD python3 face_detection_init_script.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
# Detección de rostros en vídeos digitales: demostración | ||
Este es una demostración de la capacidad de los modelos generados de poder detectar rostros en vídeos. Este repositorio forma parte del Trabajo de Fin de Grado realizado por estudiantes de Ingeniería Informática e Ingeniería del Software de la Facultad de Informática de la Universidad Complutense de Madrid en 2020. | ||
|
||
Los miembros que forman parte de dicho grupo de trabajo son los siguientes: | ||
+ Arturo Barbero Pérez | ||
+ Alejandro Cabezas Garríguez | ||
+ José Morcuende Sierra | ||
|
||
En este documento se encuentra el manual de utilización de dicho código, así como el manual de instalación correspondiente. El documento se divide en los siguientes apartados: | ||
1. **Manual de instalación** | ||
2. **Manual de uso** | ||
|
||
## 1. Manual de instalación | ||
### 1.1 Linux (Recomendado) | ||
Para sistemas Linux se realizará la instalación vía **Docker** para simplificarla. Por lo tanto, son necesarios los siguientes requisitos: | ||
+ Docker (Versión 19.03 o superior): En [este enlace](https://docs.docker.com/engine/install/) podrás encontrar un manual de instalación de Docker orientado para los Sistemas Operativos de **CenOS, Debian, Fedora, Raspbian y Ubuntu**. | ||
|
||
Para la instalación, lo primero que debemos realizar es descargar el repositorio, a través del gestor de descargas de GitLab o a través del siguiente comando: | ||
|
||
git clone http://gitlab.fdi.ucm.es/arturobp/facedetection_tfg.git | ||
|
||
Lo siguientes que realizaremos será entrar en el directorio donde hemos descargado el repositorio: | ||
|
||
cd facedetection_tfg | ||
|
||
Una vez situados en la carpeta, deberemos ejecutar el siguiente comando: | ||
|
||
./init.sh | ||
|
||
Dicho comando realizará todo el trabajo por nosotros. Una vez el proceso haya concluido, se iniciará la demostración, por lo que si se ha llegado a este punto es recomendable navegar al apartado del manual de uso. En caso de haber algún problema al utilizar Docker, podría intentarse también la instalación especificada para el sistema Windows, dado que también serviría para Linux. | ||
|
||
### 1.2 Windows | ||
Debido a diferentes problemas de compatibilidad, no ha sido posible realizar la instalación del software a través de **Docker**, por lo que realizaremos la instalación de manera manual. Para ello, necesitamos los siguientes requisitos: | ||
+ Python (Versión 3.7): En [este enlace](https://www.python.org/downloads/release/python-370/) encontrarás la página oficial de python para poder descargarlo. La versióm debe ser de 64 bits. | ||
+ Además, según la página de TensorFlow, se debe disponer de una tarjeta GPU NVIDIA con capacidad de procesamiento CUDA 3.5 o versiones posteriores. Es posible que esto pueda ocasionar futuros errores. | ||
|
||
Una vez hemos descargado Python, debemos descargar el repositorio a través del gestor de descargar de GitLab o a través del siguiente comando si disponemos del cliente de GIT para windows (el cual puede descargarse a través del [siguiente enlace](https://git-scm.com/downloads)) | ||
|
||
git clone http://gitlab.fdi.ucm.es/arturobp/facedetection_tfg.git | ||
|
||
Una vez hemos descargado el repositorio, debemos acceder a él y, una vez dentro de la carpeta, deberemos abrir la consola de comandos de Windows y escribir el siguiente comando: | ||
|
||
pip install -r requirements.txt | ||
|
||
Dicho comando importará todas las librerías necesarias para su ejecución. **Es muy importante** que a la hora de realizar el comando estemos situados dentro de la carpeta del repositorio, de lo contrario no funcionará. | ||
|
||
Además, debemos introducir el siguiente comando para instalar la versión de TensowFlow no adaptada a GPU: | ||
|
||
pip install tensorflow==1.14.0 | ||
|
||
Una vez instaladas las librerías necesarias, el proceso de instalación habrá concluído y, por tanto, es recomendable situarse sobre el apartado de manual de uso. | ||
|
||
## 2. Manual de uso | ||
|
||
### 2.1 Contenido | ||
El repositorio contiene varias imágenes y vídeos de prueba para que puedan ser usados sin necesidad de importarlos, de tal manera que se ahorra tiempo de cara a la ejecución. Dichos archivos si situan en las carpetas de `images` y `videos`. | ||
|
||
También podemos encontrar los modelos generados, al igual que algunos archivos auxiliar usada para la creación de los marcos a la hora de pintar la detección en la imagen. | ||
|
||
Por otro lado, encontraremos ficheros necesarios para la instalación y ejecución correcta, como son el `Dockerfile`, los script bash y otros. | ||
|
||
Por último, encontraremos un archivo llamado `config.py`, donde se detallan las configuraciones que se pueden realizar sobre la demostración y que se deben cambiar **antes de arrancar la aplicación**. Para saber más detalles sobre este archivo, recomendamos entrar en él puesto que es ahí donde se indica todo lo necesario. | ||
|
||
Al ejecutar la aplicación, nos encontraremos con la ventana principal de esta. Dicha ventana contiene un menú con las siguientes opciones: | ||
|
||
1. Detectar rostros en un vídeo local | ||
2. Detectar rostros en un vídeo de YouTube | ||
3. Detectar rostros en una transmisión en directo de Twitch | ||
4. Detectar rostros a través de la Webcam del ordenador | ||
5. Detectar rostros en imágenes | ||
|
||
Si seleccionamos las opciones 2 y 3, nos pedirá un enlace, el cual debe ser o bien uno que conduzca a un vídeo o directo de YouTube o bien uno que nos lleve a un directo de Twitch. La opción 1 comenzará con la detección del vídeo situado en la carpeta de `videos`. Dicho vídeo puede cambiarse si ajustamos el parámetro apropiado dentro del archivo de configuración explicado anteriomente. Si seleccionamos la opción 4, la Webcam se activiará y podremos detectar rostros en tiempo real. Si seleccionamos la opción 5, las imágenes situadas en la carpeta `images` comenzarán a pasar por el detector. Una vez analizadas todas, los resultados se almacenarán dentro de la carpeta `outputImages` situada en la raiz de este proyecto y se creará cuando el proceso finalice. | ||
|
||
**Importante**: El script `face_detection_init_script.py` contiene llamadas a scripts de python. Estas llamadas se realizan usando "python3 ...", pero podría ser que su sistema no cuente con dicho comando. Es por ello que puede modificarse el script para poner "python ..." y así evitar futuros problemas. | ||
|
||
Para salir de cualquiera de las opciones, basta con pulsar `Ctrl + C` para poder salir de la aplicación. El resultado de la detección se almacenará en un archivo llamado `detectedFaces.avi` que se creará en la raíz de este repositorio cuando finalice la aplicación, bien por la finalización del vídeo en cuestión o bien por forzar su salida. Dicho archivo contiene el vídeo analizado. | ||
|
||
### 2.2 Linux | ||
Como hemos realizado la instalación a través de docker, una vez esta ha concluido nos encontramos con la pantalla principal de la aplicación. Si deseamos terminar la ejecución, basta con pulsar `Ctrl + C`. Si deseamos volver a ejecutarlo, unicamente deberemos ejecutar el siguiente comando: | ||
|
||
./run_face_detections.sh | ||
|
||
### 2.3 Windows | ||
Para poder arrancar la aplicación y situarnos en la ventana principal de esta, deberemos ejecutar el siguiente comando una vez finalizada la instalación: | ||
|
||
python face_detection_init_script.py | ||
|
||
### 2.4 Comandos | ||
En caso de que la ejecución del script `face_detection_init_script.py` no haya funcionado por alguna razón, a continuación se muestran comandos que harán exactamente lo mismo que el script anterior, pero de una manera más gráfica: | ||
|
||
- python video_detector.py -v : Ejecuta el detector con el vídeo preconfigurado en el archivo config.py | ||
- python video_detector.py -y [URL] : Ejecuta el detector con vídeos de YouTube | ||
- python video_detector.py -t [URL] : Ejecuta el detector con retransmisiones de Twitch | ||
- python video_detector.py -w : Ejecutar el detector con la Webcam | ||
- python image_detector.py : Ejecuta el detector en imágenes situadas en la carpeta images. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import os | ||
|
||
''' | ||
Permite asignar la ruta de un modelo para utilizarlo en la detección. Hay que cambiar el segundo parámetro de la función | ||
"join". Por defecto se usa en tiempo real. | ||
Opciones: | ||
---------------------------------------------------- | ||
En videos: "models/faster_inceptionResnet_videos/" | ||
En tiempo real: "models/faster_inception_realtime/" | ||
---------------------------------------------------- | ||
''' | ||
MODEL_PATH = os.path.join('./', 'models/faster_inception_realtime/') | ||
|
||
|
||
''' | ||
Permite asignar una ruta de un vídeo local sobre el que se quiera utilizar la detección facial. Se debe adjuntar el vídeo | ||
en la carpeta 'videos' y cambiar el nombre en la constante. Por defecto, se ejecutará sobre un vídeo que proporcionamos | ||
de prueba. El vídeo que se genere con las detecciones se guardará en la raíz del proyecto. | ||
''' | ||
PATH_VIDEO = os.path.join('./videos/', 'joker.mp4') | ||
|
||
|
||
''' | ||
Permite asignar una ruta que indique la carpeta donde se encuentran las fotos sobre las que queremos realizar la detección | ||
facial con el fichero 'image_detector.py'. Las imagenes deben ser en formato JPG. Por defecto se ha establecido en la carpeta | ||
'images' que contiene unos ejemplos de prueba. | ||
Además, se puede configurar una ruta para las imágenes de salida. | ||
''' | ||
PATH_TO_IMAGES = os.path.join('./', 'images/') | ||
PATH_TO_OUTPUT_IMAGES = os.path.join('./', 'outputImages/') | ||
|
||
|
||
|
||
|
||
''' | ||
--------------------------------------------------------- | ||
ATENCION: Las siguientes constantes no se deben modificar | ||
--------------------------------------------------------- | ||
''' | ||
# Ruta al grafo de inferencia que se usa para realizar la detección | ||
PATH_TO_CKPT = os.path.join(MODEL_PATH, 'frozen_inference_graph.pb') | ||
|
||
# Ruta a las etiquetas que usa TensorFlow | ||
PATH_TO_LABELS = os.path.join('./', 'face_label_map.pbtxt') | ||
|
||
# Número de clases a detectar | ||
NUM_CLASSES = 1 | ||
|
||
# Obtención del nombre de las imagenes en formato .jpg de la ruta que especifica el usuario | ||
L = [] | ||
for n in os.listdir(PATH_TO_IMAGES): | ||
if n.endswith('jpg'): | ||
L.append(n) | ||
L.sort() | ||
IMAGES_PATH = [ os.path.join(PATH_TO_IMAGES, i) for i in L ] | ||
|
||
# Tamaño de imagen necesario para 'image_detector.py' | ||
IMAGE_SIZE = (12, 8) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import os | ||
import config | ||
|
||
print ("\n\n\n============ DETECCIÓN DE ROSTROS EN VÍDEOS ===========") | ||
|
||
|
||
def showMenu(): | ||
print ("1 - Detectar rostros en un vídeo en local") | ||
print ("2 - Detectar rostros en un vídeo de youtube") | ||
print ("3 - Detectar rostros en un directo de twitch") | ||
print ("4 - Detectar rostros usando la webcam") | ||
print ("5 - Detectar rostros en imágenes") | ||
|
||
option = -1 | ||
while option < 0 or option > 5: | ||
try: | ||
showMenu() | ||
option = int(input("Introduce una opción: ")) | ||
except ValueError: | ||
print("¡El valor debe ser un entero!\n") | ||
option = -1 | ||
|
||
if option == 1: | ||
print("Detectando rostros en vídeo situado en el archivo config...") | ||
os.system("python3 video_detector.py -v") | ||
|
||
elif option == 2: | ||
link = str(input("Introduzca enlace: ")) | ||
os.system("python3 video_detector.py -y {}".format(link)) | ||
print(link) | ||
elif option == 3: | ||
link = str(input("Introduzca enlace: ")) | ||
os.system("python3 video_detector.py -t {}".format(link)) | ||
print(link) | ||
elif option == 4: | ||
print("Arrancando detección en webcam...") | ||
os.system("python3 video_detector.py -w") | ||
elif option == 5: | ||
print("Arrancando detección sobre imagenes...") | ||
os.system("python3 image_detector.py") | ||
print("Las detecciones se han realizado correctamente en la ruta: {}".format(config.PATH_TO_OUTPUT_IMAGES)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
item { | ||
id: 1 | ||
name: 'face' | ||
display_name: "face" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
item { | ||
id: 1 | ||
name: 'unmask' | ||
display_name: "No Mask" | ||
} | ||
|
||
item { | ||
id: 2 | ||
name: 'mask' | ||
display_name: "Mask" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
# Código adaptado de la siguiente fuente: https://tensorflow-object-detection-api-tutorial.readthedocs.io/en/latest/camera.html | ||
|
||
import numpy as np | ||
import os | ||
import tensorflow as tf | ||
import config | ||
from matplotlib import pyplot as plt | ||
from PIL import Image | ||
from object_detection.utils import label_map_util | ||
from object_detection.utils import visualization_utils as vis_util | ||
from object_detection.utils import ops as utils_ops | ||
|
||
# Se comprueba que las rutas existan | ||
modelOK = os.path.exists(config.MODEL_PATH) | ||
imagesOK = os.path.exists(config.PATH_TO_IMAGES) | ||
outputOK = os.path.exists(config.PATH_TO_OUTPUT_IMAGES) | ||
|
||
|
||
def loadTensorFlowModel(): | ||
""" | ||
Carga el modelo de TensorFlow en memoria. Este modelo se escoge en el fichero de configuración "config.py" | ||
@return: detection_graph (Objeto simbolizando el grafo de detección a usar en cada fotograma), | ||
category_index (Indice perteneciente a la etiqueta que se va a mostrar en la detección) | ||
""" | ||
detection_graph = tf.Graph() | ||
with detection_graph.as_default(): | ||
od_graph_def = tf.GraphDef() | ||
with tf.gfile.GFile(config.PATH_TO_CKPT, 'rb') as fid: | ||
serialized_graph = fid.read() | ||
od_graph_def.ParseFromString(serialized_graph) | ||
tf.import_graph_def(od_graph_def, name='') | ||
|
||
label_map = label_map_util.load_labelmap(config.PATH_TO_LABELS) | ||
categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=config.NUM_CLASSES, | ||
use_display_name=True) | ||
category_index = label_map_util.create_category_index(categories) | ||
|
||
return detection_graph, category_index | ||
|
||
|
||
def run_detection_for_single_image(image, graph): | ||
""" | ||
Esta funcion se encarga de realizar la detección para una imagen en especifico. Utiliza todas las funciones necesarias | ||
de tensorflow para poder llevar a cabo esta detección. | ||
@param image: Imagen sobre la que se debe hacer la detección facial | ||
@param graph: Objeto simbolizando el grafo de detección a usar en cada fotograma | ||
@return: output_dict (Diccionario con las caras encontradas en la imagen) | ||
""" | ||
with graph.as_default(): | ||
with tf.Session() as sess: | ||
ops = tf.get_default_graph().get_operations() | ||
all_tensor_names = {output.name for op in ops for output in op.outputs} | ||
tensor_dict = {} | ||
for key in [ | ||
'num_detections', 'detection_boxes', 'detection_scores', | ||
'detection_classes', 'detection_masks' | ||
]: | ||
tensor_name = key + ':0' | ||
if tensor_name in all_tensor_names: | ||
tensor_dict[key] = tf.get_default_graph().get_tensor_by_name( | ||
tensor_name) | ||
if 'detection_masks' in tensor_dict: | ||
detection_boxes = tf.squeeze(tensor_dict['detection_boxes'], [0]) | ||
detection_masks = tf.squeeze(tensor_dict['detection_masks'], [0]) | ||
|
||
real_num_detection = tf.cast(tensor_dict['num_detections'][0], tf.int32) | ||
detection_boxes = tf.slice(detection_boxes, [0, 0], [real_num_detection, -1]) | ||
detection_masks = tf.slice(detection_masks, [0, 0, 0], [real_num_detection, -1, -1]) | ||
detection_masks_reframed = utils_ops.reframe_box_masks_to_image_masks( | ||
detection_masks, detection_boxes, image.shape[0], image.shape[1]) | ||
detection_masks_reframed = tf.cast( | ||
tf.greater(detection_masks_reframed, 0.5), tf.uint8) | ||
|
||
tensor_dict['detection_masks'] = tf.expand_dims( | ||
detection_masks_reframed, 0) | ||
image_tensor = tf.get_default_graph().get_tensor_by_name('image_tensor:0') | ||
|
||
# Realiza la inferencia | ||
output_dict = sess.run(tensor_dict, | ||
feed_dict={image_tensor: np.expand_dims(image, 0)}) | ||
|
||
output_dict['num_detections'] = int(output_dict['num_detections'][0]) | ||
output_dict['detection_classes'] = output_dict[ | ||
'detection_classes'][0].astype(np.uint8) | ||
output_dict['detection_boxes'] = output_dict['detection_boxes'][0] | ||
output_dict['detection_scores'] = output_dict['detection_scores'][0] | ||
if 'detection_masks' in output_dict: | ||
output_dict['detection_masks'] = output_dict['detection_masks'][0] | ||
return output_dict | ||
|
||
|
||
def performDetection(detection_graph, category_index, image_path, i): | ||
""" | ||
Esta funcion se encarga de realizar la detección. Prepara la imagen, infiere sobre ella y posteriormente la guarda | ||
en el directorio de salida que tenga especificado el usuario en el archivo 'config.py' | ||
@param detection_graph: Objeto simbolizando el grafo de detección a usar en cada fotograma | ||
@param category_index: Indice perteneciente a la etiqueta que se va a mostrar en la detección | ||
@param image_path: Ruta de la imagen a usar | ||
@param i: Número de imagen procesada | ||
""" | ||
# Preparamos la imagen | ||
image = Image.open(image_path) | ||
image_np = np.array(image) | ||
image_np_expanded = np.expand_dims(image_np, axis=0) | ||
|
||
# Realizamos la detección | ||
output_dict = run_detection_for_single_image(image_np, detection_graph) | ||
|
||
# Se dibuja el marco en el fotograma | ||
vis_util.visualize_boxes_and_labels_on_image_array( | ||
image_np, | ||
output_dict['detection_boxes'], | ||
output_dict['detection_classes'], | ||
output_dict['detection_scores'], | ||
category_index, | ||
instance_masks=output_dict.get('detection_masks'), | ||
use_normalized_coordinates=True, | ||
line_thickness=4, ) | ||
|
||
# Se guarda la imagen en su respectivo directorio | ||
plt.figure(figsize=config.IMAGE_SIZE) | ||
plt.imsave(config.PATH_TO_OUTPUT_IMAGES + str(i) + '.jpg', image_np) | ||
|
||
|
||
if __name__ == "__main__": | ||
|
||
if modelOK and imagesOK: | ||
if not os.path.exists(config.PATH_TO_OUTPUT_IMAGES): | ||
os.makedirs(config.PATH_TO_OUTPUT_IMAGES) | ||
|
||
# Se obtiene el grafo de detección | ||
detection_graph, category_index = loadTensorFlowModel() | ||
|
||
# Se comienza a iterar sobre cada una de las imagenes | ||
i = 0 | ||
for image_path in config.IMAGES_PATH: | ||
i += 1 | ||
print("Procesando imagen {}".format(i)) | ||
performDetection(detection_graph, category_index, image_path, i) | ||
else: | ||
print("Ha habido un error. Comprueba el fichero 'config.py'") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
docker build -t face_detection_app . | ||
docker create -ti --device=/dev/video0:/dev/video0 -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY --name=face_detection_app face_detection_app | ||
xhost +local:root | ||
./run_face_detection.sh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
model_checkpoint_path: "model.ckpt" | ||
all_model_checkpoint_paths: "model.ckpt" |
Git LFS file not shown
Oops, something went wrong.