Spaces:
Build error
Build error
Commit
·
aafeadf
1
Parent(s):
9fd78b1
Mejorar visualización y persistencia de la base de datos de rostros
Browse files- face_database_utils.py +40 -1
- streamlit_app.py +73 -50
face_database_utils.py
CHANGED
|
@@ -19,6 +19,14 @@ def save_face_database(database):
|
|
| 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():
|
|
@@ -36,6 +44,10 @@ def save_face_database(database):
|
|
| 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)}")
|
|
@@ -133,4 +145,31 @@ def import_database_json(json_file):
|
|
| 133 |
return imported_db
|
| 134 |
except Exception as e:
|
| 135 |
st.error(f"Error al importar la base de datos: {str(e)}")
|
| 136 |
-
return {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
database (dict): La base de datos de rostros a guardar
|
| 20 |
"""
|
| 21 |
try:
|
| 22 |
+
# Verificar si hay datos para guardar
|
| 23 |
+
if not database:
|
| 24 |
+
# Si la base de datos está vacía, eliminar el archivo si existe
|
| 25 |
+
if os.path.exists(DATABASE_FILE):
|
| 26 |
+
os.remove(DATABASE_FILE)
|
| 27 |
+
st.sidebar.write("Database was empty - removed existing file")
|
| 28 |
+
return True
|
| 29 |
+
|
| 30 |
# Convertir numpy arrays a listas para poder serializarlas
|
| 31 |
serializable_db = {}
|
| 32 |
for name, info in database.items():
|
|
|
|
| 44 |
# Guardar en un archivo pickle
|
| 45 |
with open(DATABASE_FILE, 'wb') as f:
|
| 46 |
pickle.dump(serializable_db, f)
|
| 47 |
+
|
| 48 |
+
# Verificar que el archivo se creó correctamente
|
| 49 |
+
if os.path.exists(DATABASE_FILE):
|
| 50 |
+
st.sidebar.write(f"Database saved to {DATABASE_FILE} ({len(serializable_db)} entries)")
|
| 51 |
return True
|
| 52 |
except Exception as e:
|
| 53 |
st.error(f"Error al guardar la base de datos: {str(e)}")
|
|
|
|
| 145 |
return imported_db
|
| 146 |
except Exception as e:
|
| 147 |
st.error(f"Error al importar la base de datos: {str(e)}")
|
| 148 |
+
return {}
|
| 149 |
+
|
| 150 |
+
def print_database_info():
|
| 151 |
+
"""
|
| 152 |
+
Imprime información sobre la base de datos actual para depuración.
|
| 153 |
+
"""
|
| 154 |
+
if 'face_database' in st.session_state:
|
| 155 |
+
db = st.session_state.face_database
|
| 156 |
+
st.sidebar.write("--- Database Debug Info ---")
|
| 157 |
+
st.sidebar.write(f"Database contains {len(db)} entries")
|
| 158 |
+
|
| 159 |
+
# Mostrar nombres en la base de datos
|
| 160 |
+
if db:
|
| 161 |
+
names = list(db.keys())
|
| 162 |
+
st.sidebar.write(f"Names in database: {', '.join(names)}")
|
| 163 |
+
|
| 164 |
+
# Mostrar detalles del primer elemento
|
| 165 |
+
if names:
|
| 166 |
+
first_entry = db[names[0]]
|
| 167 |
+
st.sidebar.write(f"Sample entry for '{names[0]}':")
|
| 168 |
+
if 'embeddings' in first_entry:
|
| 169 |
+
st.sidebar.write(f"- Has {len(first_entry['embeddings'])} embeddings")
|
| 170 |
+
st.sidebar.write(f"- Models: {', '.join(first_entry['models'])}")
|
| 171 |
+
st.sidebar.write(f"- Count: {first_entry['count']}")
|
| 172 |
+
elif 'embedding' in first_entry:
|
| 173 |
+
st.sidebar.write("- Has single embedding (old format)")
|
| 174 |
+
else:
|
| 175 |
+
st.sidebar.write("Database is empty")
|
streamlit_app.py
CHANGED
|
@@ -15,7 +15,7 @@ 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
|
|
@@ -1441,9 +1441,14 @@ def main():
|
|
| 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"])
|
| 1449 |
|
|
@@ -1570,18 +1575,29 @@ def main():
|
|
| 1570 |
|
| 1571 |
# Guardar la base de datos actualizada
|
| 1572 |
if DATABASE_UTILS_AVAILABLE:
|
| 1573 |
-
|
|
|
|
| 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}")
|
|
|
|
|
|
|
|
|
|
| 1579 |
else:
|
| 1580 |
st.error("Failed to extract embeddings. Please try again with a clearer image.")
|
| 1581 |
|
| 1582 |
# Mostrar tabla de rostros registrados
|
| 1583 |
st.subheader("Registered Faces")
|
| 1584 |
|
|
|
|
|
|
|
|
|
|
| 1585 |
if 'face_database' in st.session_state and st.session_state.face_database:
|
| 1586 |
# Inicializar variables para la tabla
|
| 1587 |
data = []
|
|
@@ -1607,58 +1623,65 @@ def main():
|
|
| 1607 |
"Models": models
|
| 1608 |
})
|
| 1609 |
|
| 1610 |
-
#
|
| 1611 |
-
|
| 1612 |
-
df = pd.DataFrame(data)
|
| 1613 |
|
| 1614 |
-
#
|
| 1615 |
-
|
| 1616 |
-
|
| 1617 |
-
|
| 1618 |
-
|
| 1619 |
-
with col2:
|
| 1620 |
-
st.write(row["Images"])
|
| 1621 |
-
with col3:
|
| 1622 |
-
st.write(row["Embeddings"])
|
| 1623 |
-
with col4:
|
| 1624 |
-
st.write(row["Models"])
|
| 1625 |
-
with col5:
|
| 1626 |
-
if st.button("Delete", key=f"delete_{row['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 |
-
|
| 1638 |
-
# Botón para eliminar todos los registros
|
| 1639 |
-
if st.button("Delete All Registered Faces"):
|
| 1640 |
-
# Mostrar confirmación
|
| 1641 |
-
if 'confirm_delete_all' not in st.session_state:
|
| 1642 |
-
st.session_state.confirm_delete_all = False
|
| 1643 |
|
| 1644 |
-
|
| 1645 |
-
|
| 1646 |
-
col1, col2 = st.columns(2)
|
| 1647 |
with col1:
|
| 1648 |
-
|
| 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()
|
| 1658 |
with col2:
|
| 1659 |
-
|
| 1660 |
-
|
| 1661 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1662 |
else:
|
| 1663 |
st.info("No faces registered yet. Use the form above to register faces.")
|
| 1664 |
|
|
|
|
| 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, print_database_info
|
| 19 |
DATABASE_UTILS_AVAILABLE = True
|
| 20 |
except ImportError:
|
| 21 |
DATABASE_UTILS_AVAILABLE = False
|
|
|
|
| 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 |
+
st.sidebar.write(f"Loaded face database with {len(st.session_state.face_database)} entries")
|
| 1445 |
else:
|
| 1446 |
st.session_state.face_database = {}
|
| 1447 |
|
| 1448 |
+
# Imprimir información de depuración
|
| 1449 |
+
if DATABASE_UTILS_AVAILABLE:
|
| 1450 |
+
print_database_info()
|
| 1451 |
+
|
| 1452 |
# Crear pestañas para las diferentes funcionalidades
|
| 1453 |
tab1, tab2, tab3 = st.tabs(["Register Face", "Image Recognition", "Real-time Recognition"])
|
| 1454 |
|
|
|
|
| 1575 |
|
| 1576 |
# Guardar la base de datos actualizada
|
| 1577 |
if DATABASE_UTILS_AVAILABLE:
|
| 1578 |
+
save_success = save_face_database(st.session_state.face_database)
|
| 1579 |
+
if save_success:
|
| 1580 |
st.info("Face database saved successfully!")
|
| 1581 |
+
# Mostrar información actualizada de la base de datos
|
| 1582 |
+
print_database_info()
|
| 1583 |
+
else:
|
| 1584 |
+
st.error("Error saving face database!")
|
| 1585 |
|
| 1586 |
# Mostrar la imagen con el rostro detectado
|
| 1587 |
processed_image, _ = process_face_detections(image, [bboxes[0]], confidence_threshold)
|
| 1588 |
st.image(cv2.cvtColor(processed_image, cv2.COLOR_BGR2RGB), caption=f"Registered face: {person_name}")
|
| 1589 |
+
|
| 1590 |
+
# Forzar recarga de la interfaz para mostrar el rostro registrado
|
| 1591 |
+
st.experimental_rerun()
|
| 1592 |
else:
|
| 1593 |
st.error("Failed to extract embeddings. Please try again with a clearer image.")
|
| 1594 |
|
| 1595 |
# Mostrar tabla de rostros registrados
|
| 1596 |
st.subheader("Registered Faces")
|
| 1597 |
|
| 1598 |
+
# Debug de contenido de base de datos
|
| 1599 |
+
st.sidebar.write(f"Face database contains {len(st.session_state.face_database)} entries at display time")
|
| 1600 |
+
|
| 1601 |
if 'face_database' in st.session_state and st.session_state.face_database:
|
| 1602 |
# Inicializar variables para la tabla
|
| 1603 |
data = []
|
|
|
|
| 1623 |
"Models": models
|
| 1624 |
})
|
| 1625 |
|
| 1626 |
+
# Debug de los datos procesados
|
| 1627 |
+
st.sidebar.write(f"Processed {len(data)} entries for display")
|
|
|
|
| 1628 |
|
| 1629 |
+
# Verificar si hay datos para mostrar
|
| 1630 |
+
if data:
|
| 1631 |
+
# Crear DataFrame
|
| 1632 |
+
import pandas as pd
|
| 1633 |
+
df = pd.DataFrame(data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1634 |
|
| 1635 |
+
# Mostrar tabla con botones de eliminación
|
| 1636 |
+
for i, row in df.iterrows():
|
| 1637 |
+
col1, col2, col3, col4, col5 = st.columns([3, 2, 2, 4, 2])
|
| 1638 |
with col1:
|
| 1639 |
+
st.write(row["Name"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1640 |
with col2:
|
| 1641 |
+
st.write(row["Images"])
|
| 1642 |
+
with col3:
|
| 1643 |
+
st.write(row["Embeddings"])
|
| 1644 |
+
with col4:
|
| 1645 |
+
st.write(row["Models"])
|
| 1646 |
+
with col5:
|
| 1647 |
+
if st.button("Delete", key=f"delete_{row['Name']}"):
|
| 1648 |
+
# Eliminar el registro
|
| 1649 |
+
if row["Name"] in st.session_state.face_database:
|
| 1650 |
+
del st.session_state.face_database[row["Name"]]
|
| 1651 |
+
|
| 1652 |
+
# Guardar la base de datos actualizada
|
| 1653 |
+
if DATABASE_UTILS_AVAILABLE:
|
| 1654 |
+
save_face_database(st.session_state.face_database)
|
| 1655 |
+
|
| 1656 |
+
st.success(f"Deleted {row['Name']} from the database.")
|
| 1657 |
+
st.experimental_rerun()
|
| 1658 |
+
|
| 1659 |
+
# Botón para eliminar todos los registros
|
| 1660 |
+
if st.button("Delete All Registered Faces"):
|
| 1661 |
+
# Mostrar confirmación
|
| 1662 |
+
if 'confirm_delete_all' not in st.session_state:
|
| 1663 |
+
st.session_state.confirm_delete_all = False
|
| 1664 |
+
|
| 1665 |
+
if not st.session_state.confirm_delete_all:
|
| 1666 |
+
st.warning("Are you sure you want to delete all registered faces? This action cannot be undone.")
|
| 1667 |
+
col1, col2 = st.columns(2)
|
| 1668 |
+
with col1:
|
| 1669 |
+
if st.button("Yes, delete all"):
|
| 1670 |
+
st.session_state.face_database = {}
|
| 1671 |
+
|
| 1672 |
+
# Guardar la base de datos vacía
|
| 1673 |
+
if DATABASE_UTILS_AVAILABLE:
|
| 1674 |
+
save_face_database({})
|
| 1675 |
+
|
| 1676 |
+
st.session_state.confirm_delete_all = False
|
| 1677 |
+
st.success("All registered faces have been deleted.")
|
| 1678 |
+
st.experimental_rerun()
|
| 1679 |
+
with col2:
|
| 1680 |
+
if st.button("Cancel"):
|
| 1681 |
+
st.session_state.confirm_delete_all = False
|
| 1682 |
+
st.experimental_rerun()
|
| 1683 |
+
else:
|
| 1684 |
+
st.info("No faces registered yet. Use the form above to register faces.")
|
| 1685 |
else:
|
| 1686 |
st.info("No faces registered yet. Use the form above to register faces.")
|
| 1687 |
|