jarondon82 commited on
Commit
9fd78b1
·
1 Parent(s): 7d31590

Implementar persistencia de base de datos de rostros

Browse files
Files changed (2) hide show
  1. face_database_utils.py +136 -0
  2. streamlit_app.py +62 -1
face_database_utils.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Utilidades para manejar la persistencia de la base de datos de rostros.
3
+ """
4
+ import os
5
+ import pickle
6
+ import streamlit as st
7
+ import json
8
+ import base64
9
+ import numpy as np
10
+
11
+ # Configurar ruta para la base de datos
12
+ DATABASE_FILE = "face_database.pkl"
13
+
14
+ def save_face_database(database):
15
+ """
16
+ Guarda la base de datos de rostros en un archivo persistente.
17
+
18
+ Args:
19
+ database (dict): La base de datos de rostros a guardar
20
+ """
21
+ try:
22
+ # Convertir numpy arrays a listas para poder serializarlas
23
+ serializable_db = {}
24
+ for name, info in database.items():
25
+ serializable_db[name] = {}
26
+ # Manejar diferentes formatos de la base de datos
27
+ if 'embeddings' in info:
28
+ serializable_db[name]['embeddings'] = [emb.tolist() if isinstance(emb, np.ndarray) else emb for emb in info['embeddings']]
29
+ serializable_db[name]['models'] = info['models']
30
+ serializable_db[name]['count'] = info['count']
31
+ elif 'embedding' in info:
32
+ # Formato antiguo
33
+ serializable_db[name]['embedding'] = info['embedding'].tolist() if isinstance(info['embedding'], np.ndarray) else info['embedding']
34
+ serializable_db[name]['count'] = info.get('count', 1)
35
+
36
+ # Guardar en un archivo pickle
37
+ with open(DATABASE_FILE, 'wb') as f:
38
+ pickle.dump(serializable_db, f)
39
+ return True
40
+ except Exception as e:
41
+ st.error(f"Error al guardar la base de datos: {str(e)}")
42
+ return False
43
+
44
+ def load_face_database():
45
+ """
46
+ Carga la base de datos de rostros desde un archivo persistente.
47
+
48
+ Returns:
49
+ dict: La base de datos de rostros cargada, o un diccionario vacío si no existe el archivo.
50
+ """
51
+ if not os.path.exists(DATABASE_FILE):
52
+ return {}
53
+
54
+ try:
55
+ with open(DATABASE_FILE, 'rb') as f:
56
+ database = pickle.load(f)
57
+
58
+ # Convertir listas a numpy arrays
59
+ for name, info in database.items():
60
+ if 'embeddings' in info:
61
+ database[name]['embeddings'] = [np.array(emb) if isinstance(emb, list) else emb for emb in info['embeddings']]
62
+ elif 'embedding' in info:
63
+ database[name]['embedding'] = np.array(info['embedding']) if isinstance(info['embedding'], list) else info['embedding']
64
+
65
+ return database
66
+ except Exception as e:
67
+ st.error(f"Error al cargar la base de datos: {str(e)}")
68
+ return {}
69
+
70
+ def export_database_json():
71
+ """
72
+ Exporta la base de datos a un archivo JSON para compartir o hacer backup.
73
+
74
+ Returns:
75
+ str: Ruta al archivo JSON exportado.
76
+ """
77
+ try:
78
+ if 'face_database' in st.session_state and st.session_state.face_database:
79
+ # Crear una versión serializable de la base de datos
80
+ serializable_db = {}
81
+ for name, info in st.session_state.face_database.items():
82
+ serializable_db[name] = {}
83
+ if 'embeddings' in info:
84
+ serializable_db[name]['embeddings'] = [
85
+ base64.b64encode(np.array(emb).tobytes()).decode('utf-8')
86
+ for emb in info['embeddings']
87
+ ]
88
+ serializable_db[name]['models'] = info['models']
89
+ serializable_db[name]['count'] = info['count']
90
+ elif 'embedding' in info:
91
+ serializable_db[name]['embedding'] = base64.b64encode(
92
+ np.array(info['embedding']).tobytes()
93
+ ).decode('utf-8')
94
+ serializable_db[name]['count'] = info.get('count', 1)
95
+
96
+ # Guardar en un archivo JSON
97
+ export_file = "face_database_export.json"
98
+ with open(export_file, 'w') as f:
99
+ json.dump(serializable_db, f, indent=2)
100
+
101
+ return export_file
102
+ return None
103
+ except Exception as e:
104
+ st.error(f"Error al exportar la base de datos: {str(e)}")
105
+ return None
106
+
107
+ def import_database_json(json_file):
108
+ """
109
+ Importa una base de datos desde un archivo JSON.
110
+
111
+ Args:
112
+ json_file: El archivo JSON a importar
113
+
114
+ Returns:
115
+ dict: La base de datos importada.
116
+ """
117
+ try:
118
+ content = json_file.read()
119
+ imported_db = json.loads(content)
120
+
121
+ # Convertir datos codificados en base64 a numpy arrays
122
+ for name, info in imported_db.items():
123
+ if 'embeddings' in info:
124
+ imported_db[name]['embeddings'] = [
125
+ np.frombuffer(base64.b64decode(emb), dtype=np.float32)
126
+ for emb in info['embeddings']
127
+ ]
128
+ elif 'embedding' in info:
129
+ imported_db[name]['embedding'] = np.frombuffer(
130
+ base64.b64decode(info['embedding']), dtype=np.float32
131
+ )
132
+
133
+ return imported_db
134
+ except Exception as e:
135
+ st.error(f"Error al importar la base de datos: {str(e)}")
136
+ return {}
streamlit_app.py CHANGED
@@ -13,6 +13,14 @@ import pickle
13
  from sklearn.metrics.pairwise import cosine_similarity # type: ignore
14
  import pandas as pd
15
 
 
 
 
 
 
 
 
 
16
  # Importar DeepFace para reconocimiento facial avanzado
17
  try:
18
  from deepface import DeepFace
@@ -1430,7 +1438,11 @@ def main():
1430
 
1431
  # Inicializar base de datos de rostros si no existe
1432
  if 'face_database' not in st.session_state:
1433
- st.session_state.face_database = {}
 
 
 
 
1434
 
1435
  # Crear pestañas para las diferentes funcionalidades
1436
  tab1, tab2, tab3 = st.tabs(["Register Face", "Image Recognition", "Real-time Recognition"])
@@ -1556,6 +1568,11 @@ def main():
1556
 
1557
  st.success(f"Face registered successfully for {person_name}!")
1558
 
 
 
 
 
 
1559
  # Mostrar la imagen con el rostro detectado
1560
  processed_image, _ = process_face_detections(image, [bboxes[0]], confidence_threshold)
1561
  st.image(cv2.cvtColor(processed_image, cv2.COLOR_BGR2RGB), caption=f"Registered face: {person_name}")
@@ -1610,6 +1627,11 @@ def main():
1610
  # Eliminar el registro
1611
  if row["Name"] in st.session_state.face_database:
1612
  del st.session_state.face_database[row["Name"]]
 
 
 
 
 
1613
  st.success(f"Deleted {row['Name']} from the database.")
1614
  st.experimental_rerun()
1615
 
@@ -1625,6 +1647,11 @@ def main():
1625
  with col1:
1626
  if st.button("Yes, delete all"):
1627
  st.session_state.face_database = {}
 
 
 
 
 
1628
  st.session_state.confirm_delete_all = False
1629
  st.success("All registered faces have been deleted.")
1630
  st.experimental_rerun()
@@ -1634,6 +1661,40 @@ def main():
1634
  st.experimental_rerun()
1635
  else:
1636
  st.info("No faces registered yet. Use the form above to register faces.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1637
 
1638
  with tab2:
1639
  st.header("Image Recognition")
 
13
  from sklearn.metrics.pairwise import cosine_similarity # type: ignore
14
  import pandas as pd
15
 
16
+ # Importar las utilidades para la base de datos de rostros
17
+ try:
18
+ from face_database_utils import save_face_database, load_face_database, export_database_json, import_database_json
19
+ DATABASE_UTILS_AVAILABLE = True
20
+ except ImportError:
21
+ DATABASE_UTILS_AVAILABLE = False
22
+ st.warning("Database utilities are not available. Face recognition data will not be persistent between sessions.")
23
+
24
  # Importar DeepFace para reconocimiento facial avanzado
25
  try:
26
  from deepface import DeepFace
 
1438
 
1439
  # Inicializar base de datos de rostros si no existe
1440
  if 'face_database' not in st.session_state:
1441
+ if DATABASE_UTILS_AVAILABLE:
1442
+ # Cargar la base de datos desde el archivo persistente
1443
+ st.session_state.face_database = load_face_database()
1444
+ else:
1445
+ st.session_state.face_database = {}
1446
 
1447
  # Crear pestañas para las diferentes funcionalidades
1448
  tab1, tab2, tab3 = st.tabs(["Register Face", "Image Recognition", "Real-time Recognition"])
 
1568
 
1569
  st.success(f"Face registered successfully for {person_name}!")
1570
 
1571
+ # Guardar la base de datos actualizada
1572
+ if DATABASE_UTILS_AVAILABLE:
1573
+ if save_face_database(st.session_state.face_database):
1574
+ st.info("Face database saved successfully!")
1575
+
1576
  # Mostrar la imagen con el rostro detectado
1577
  processed_image, _ = process_face_detections(image, [bboxes[0]], confidence_threshold)
1578
  st.image(cv2.cvtColor(processed_image, cv2.COLOR_BGR2RGB), caption=f"Registered face: {person_name}")
 
1627
  # Eliminar el registro
1628
  if row["Name"] in st.session_state.face_database:
1629
  del st.session_state.face_database[row["Name"]]
1630
+
1631
+ # Guardar la base de datos actualizada
1632
+ if DATABASE_UTILS_AVAILABLE:
1633
+ save_face_database(st.session_state.face_database)
1634
+
1635
  st.success(f"Deleted {row['Name']} from the database.")
1636
  st.experimental_rerun()
1637
 
 
1647
  with col1:
1648
  if st.button("Yes, delete all"):
1649
  st.session_state.face_database = {}
1650
+
1651
+ # Guardar la base de datos vacía
1652
+ if DATABASE_UTILS_AVAILABLE:
1653
+ save_face_database({})
1654
+
1655
  st.session_state.confirm_delete_all = False
1656
  st.success("All registered faces have been deleted.")
1657
  st.experimental_rerun()
 
1661
  st.experimental_rerun()
1662
  else:
1663
  st.info("No faces registered yet. Use the form above to register faces.")
1664
+
1665
+ # Añadir botones para importar/exportar la base de datos
1666
+ if DATABASE_UTILS_AVAILABLE:
1667
+ st.subheader("Database Management")
1668
+ col1, col2 = st.columns(2)
1669
+
1670
+ with col1:
1671
+ # Exportar base de datos
1672
+ if st.button("Export Face Database") and st.session_state.face_database:
1673
+ export_file = export_database_json()
1674
+ if export_file:
1675
+ with open(export_file, "rb") as f:
1676
+ st.download_button(
1677
+ label="Download JSON Database",
1678
+ data=f,
1679
+ file_name="face_database.json",
1680
+ mime="application/json"
1681
+ )
1682
+
1683
+ with col2:
1684
+ # Importar base de datos
1685
+ uploaded_json = st.file_uploader("Import Face Database", type=["json"], key="import_database")
1686
+ if uploaded_json is not None:
1687
+ if st.button("Process Import"):
1688
+ with st.spinner("Importing database..."):
1689
+ imported_db = import_database_json(uploaded_json)
1690
+ if imported_db:
1691
+ # Actualizar la base de datos actual
1692
+ st.session_state.face_database.update(imported_db)
1693
+
1694
+ # Guardar la base de datos actualizada
1695
+ if save_face_database(st.session_state.face_database):
1696
+ st.success("Database imported and saved successfully!")
1697
+ st.experimental_rerun()
1698
 
1699
  with tab2:
1700
  st.header("Image Recognition")