Spaces:
Build error
Build error
Commit
·
e132de2
1
Parent(s):
749f08c
Mejorar la visualización de la tabla de Registered Faces y manejar errores de imágenes
Browse files- streamlit_app.py +104 -134
streamlit_app.py
CHANGED
|
@@ -1737,157 +1737,127 @@ def main():
|
|
| 1737 |
st.error("Failed to extract embeddings. Please try again with a clearer image.")
|
| 1738 |
|
| 1739 |
# Mostrar tabla de rostros registrados
|
| 1740 |
-
|
| 1741 |
-
|
| 1742 |
-
|
| 1743 |
-
|
| 1744 |
-
|
| 1745 |
-
|
| 1746 |
-
|
|
|
|
|
|
|
| 1747 |
data = []
|
| 1748 |
|
| 1749 |
-
# Preparar datos para la tabla
|
| 1750 |
for name, info in st.session_state.face_database.items():
|
| 1751 |
-
#
|
| 1752 |
-
|
| 1753 |
-
|
| 1754 |
-
|
| 1755 |
-
|
| 1756 |
-
|
| 1757 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1758 |
|
| 1759 |
-
|
| 1760 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1761 |
|
| 1762 |
-
#
|
| 1763 |
data.append({
|
| 1764 |
"Name": name,
|
| 1765 |
-
"
|
|
|
|
| 1766 |
"Embeddings": num_embeddings,
|
| 1767 |
-
"Models":
|
| 1768 |
-
"Face": info.get('face_image', None)
|
| 1769 |
})
|
| 1770 |
|
| 1771 |
-
#
|
| 1772 |
-
st.
|
| 1773 |
|
| 1774 |
-
|
| 1775 |
-
|
| 1776 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1777 |
col_thumb, col1, col2, col3, col4, col5 = st.columns([2, 3, 2, 2, 4, 2])
|
| 1778 |
|
|
|
|
| 1779 |
with col_thumb:
|
| 1780 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1781 |
with col1:
|
| 1782 |
-
st.write("
|
| 1783 |
with col2:
|
| 1784 |
-
st.write("
|
| 1785 |
with col3:
|
| 1786 |
-
st.write("
|
| 1787 |
with col4:
|
| 1788 |
-
st.write("
|
| 1789 |
with col5:
|
| 1790 |
-
st.
|
| 1791 |
-
|
| 1792 |
-
|
| 1793 |
-
|
| 1794 |
-
col_thumb, col1, col2, col3, col4, col5 = st.columns([2, 3, 2, 2, 4, 2])
|
| 1795 |
-
|
| 1796 |
-
# Mostrar miniatura si está disponible
|
| 1797 |
-
with col_thumb:
|
| 1798 |
-
if row["Face"] is not None:
|
| 1799 |
-
# Redimensionar para crear miniatura
|
| 1800 |
-
face_img = row["Face"]
|
| 1801 |
-
h, w = face_img.shape[:2]
|
| 1802 |
-
thumbnail = cv2.resize(face_img, (w//4, h//4))
|
| 1803 |
-
st.image(cv2.cvtColor(thumbnail, cv2.COLOR_BGR2RGB), width=50)
|
| 1804 |
-
else:
|
| 1805 |
-
st.write("No image")
|
| 1806 |
|
| 1807 |
-
|
| 1808 |
-
|
| 1809 |
-
|
| 1810 |
-
|
| 1811 |
-
|
| 1812 |
-
|
| 1813 |
-
with col4:
|
| 1814 |
-
st.write(row["Models"])
|
| 1815 |
-
with col5:
|
| 1816 |
-
if st.button("Delete", key=f"delete_{row['Name']}"):
|
| 1817 |
-
# Eliminar el registro
|
| 1818 |
-
if row["Name"] in st.session_state.face_database:
|
| 1819 |
-
del st.session_state.face_database[row["Name"]]
|
| 1820 |
-
|
| 1821 |
-
# Guardar la base de datos actualizada
|
| 1822 |
-
if DATABASE_UTILS_AVAILABLE:
|
| 1823 |
-
save_face_database(st.session_state.face_database)
|
| 1824 |
-
|
| 1825 |
-
st.success(f"Deleted {row['Name']} from the database.")
|
| 1826 |
-
st.rerun()
|
| 1827 |
-
|
| 1828 |
-
# Botón para eliminar todos los registros
|
| 1829 |
-
if st.button("Delete All Registered Faces"):
|
| 1830 |
-
# Mostrar confirmación
|
| 1831 |
-
if 'confirm_delete_all' not in st.session_state:
|
| 1832 |
-
st.session_state.confirm_delete_all = False
|
| 1833 |
-
|
| 1834 |
-
if not st.session_state.confirm_delete_all:
|
| 1835 |
-
st.warning("Are you sure you want to delete all registered faces? This action cannot be undone.")
|
| 1836 |
-
col1, col2 = st.columns(2)
|
| 1837 |
-
with col1:
|
| 1838 |
-
if st.button("Yes, delete all"):
|
| 1839 |
-
st.session_state.face_database = {}
|
| 1840 |
-
|
| 1841 |
-
# Guardar la base de datos vacía
|
| 1842 |
-
if DATABASE_UTILS_AVAILABLE:
|
| 1843 |
-
save_face_database({})
|
| 1844 |
-
|
| 1845 |
-
st.session_state.confirm_delete_all = False
|
| 1846 |
-
st.success("All registered faces have been deleted.")
|
| 1847 |
-
st.rerun()
|
| 1848 |
-
with col2:
|
| 1849 |
-
if st.button("Cancel"):
|
| 1850 |
-
st.session_state.confirm_delete_all = False
|
| 1851 |
-
st.rerun()
|
| 1852 |
-
else:
|
| 1853 |
-
st.info("No faces registered yet. Use the form above to register faces.")
|
| 1854 |
-
else:
|
| 1855 |
-
st.info("No faces registered yet. Use the form above to register faces.")
|
| 1856 |
-
|
| 1857 |
-
# Añadir botones para importar/exportar la base de datos
|
| 1858 |
-
if DATABASE_UTILS_AVAILABLE:
|
| 1859 |
-
st.subheader("Database Management")
|
| 1860 |
-
col1, col2 = st.columns(2)
|
| 1861 |
-
|
| 1862 |
-
with col1:
|
| 1863 |
-
# Exportar base de datos
|
| 1864 |
-
if st.button("Export Face Database") and st.session_state.face_database:
|
| 1865 |
-
export_file = export_database_json()
|
| 1866 |
-
if export_file:
|
| 1867 |
-
with open(export_file, "rb") as f:
|
| 1868 |
-
st.download_button(
|
| 1869 |
-
label="Download JSON Database",
|
| 1870 |
-
data=f,
|
| 1871 |
-
file_name="face_database.json",
|
| 1872 |
-
mime="application/json"
|
| 1873 |
-
)
|
| 1874 |
|
| 1875 |
-
|
| 1876 |
-
|
| 1877 |
-
|
| 1878 |
-
|
| 1879 |
-
|
| 1880 |
-
|
| 1881 |
-
|
| 1882 |
-
|
| 1883 |
-
|
| 1884 |
-
|
| 1885 |
-
|
| 1886 |
-
|
| 1887 |
-
|
| 1888 |
-
|
| 1889 |
-
|
| 1890 |
-
|
| 1891 |
with tab2:
|
| 1892 |
st.header("Image Recognition")
|
| 1893 |
|
|
@@ -2265,10 +2235,10 @@ def main():
|
|
| 2265 |
scale_factor = 0.5
|
| 2266 |
h, w = img.shape[:2]
|
| 2267 |
|
| 2268 |
-
|
| 2269 |
-
|
| 2270 |
-
|
| 2271 |
-
print(
|
| 2272 |
return av.VideoFrame.from_ndarray(img, format="bgr24")
|
| 2273 |
|
| 2274 |
# Detect faces - la función ahora devuelve directamente los bboxes
|
|
|
|
| 1737 |
st.error("Failed to extract embeddings. Please try again with a clearer image.")
|
| 1738 |
|
| 1739 |
# Mostrar tabla de rostros registrados
|
| 1740 |
+
def display_registered_faces():
|
| 1741 |
+
# Display registered faces in a table
|
| 1742 |
+
st.subheader("Registered Faces")
|
| 1743 |
+
|
| 1744 |
+
if not st.session_state.face_database:
|
| 1745 |
+
st.info("No faces registered yet. Use the form above to register a face.")
|
| 1746 |
+
return
|
| 1747 |
+
|
| 1748 |
+
# Prepare data for the table
|
| 1749 |
data = []
|
| 1750 |
|
|
|
|
| 1751 |
for name, info in st.session_state.face_database.items():
|
| 1752 |
+
# Extract face image if available
|
| 1753 |
+
face_img = None
|
| 1754 |
+
if 'image' in info and info['image'] is not None:
|
| 1755 |
+
try:
|
| 1756 |
+
if is_valid_image(info['image']):
|
| 1757 |
+
face_img = info['image']
|
| 1758 |
+
else:
|
| 1759 |
+
print(f"Invalid face image for {name}")
|
| 1760 |
+
except Exception as e:
|
| 1761 |
+
print(f"Error accessing face image for {name}: {str(e)}")
|
| 1762 |
+
|
| 1763 |
+
# Count embeddings and determine models used
|
| 1764 |
+
num_embeddings = 0
|
| 1765 |
+
models_used = []
|
| 1766 |
|
| 1767 |
+
if 'embeddings' in info and info['embeddings']:
|
| 1768 |
+
num_embeddings = len(info['embeddings'])
|
| 1769 |
+
# Extract models from embeddings
|
| 1770 |
+
for emb in info['embeddings']:
|
| 1771 |
+
if 'model' in emb and emb['model'] not in models_used:
|
| 1772 |
+
models_used.append(emb['model'])
|
| 1773 |
|
| 1774 |
+
# Add row to data
|
| 1775 |
data.append({
|
| 1776 |
"Name": name,
|
| 1777 |
+
"Face": face_img,
|
| 1778 |
+
"Images": 1 if face_img is not None else 0,
|
| 1779 |
"Embeddings": num_embeddings,
|
| 1780 |
+
"Models": ", ".join(models_used) if models_used else "None"
|
|
|
|
| 1781 |
})
|
| 1782 |
|
| 1783 |
+
# Create table with custom layout
|
| 1784 |
+
col_thumb, col1, col2, col3, col4, col5 = st.columns([2, 3, 2, 2, 4, 2])
|
| 1785 |
|
| 1786 |
+
with col_thumb:
|
| 1787 |
+
st.write("**Thumbnail**")
|
| 1788 |
+
with col1:
|
| 1789 |
+
st.write("**Name**")
|
| 1790 |
+
with col2:
|
| 1791 |
+
st.write("**Images**")
|
| 1792 |
+
with col3:
|
| 1793 |
+
st.write("**Embeddings**")
|
| 1794 |
+
with col4:
|
| 1795 |
+
st.write("**Models**")
|
| 1796 |
+
with col5:
|
| 1797 |
+
st.write("**Actions**")
|
| 1798 |
+
|
| 1799 |
+
# Mostrar tabla con botones de eliminación
|
| 1800 |
+
for i, row in enumerate(data):
|
| 1801 |
col_thumb, col1, col2, col3, col4, col5 = st.columns([2, 3, 2, 2, 4, 2])
|
| 1802 |
|
| 1803 |
+
# Mostrar miniatura si está disponible
|
| 1804 |
with col_thumb:
|
| 1805 |
+
if row["Face"] is not None:
|
| 1806 |
+
try:
|
| 1807 |
+
# Redimensionar para crear miniatura
|
| 1808 |
+
face_img = row["Face"]
|
| 1809 |
+
if is_valid_image(face_img):
|
| 1810 |
+
h, w = face_img.shape[:2]
|
| 1811 |
+
thumbnail = safe_resize(face_img, (w//4, h//4))
|
| 1812 |
+
if thumbnail is not None:
|
| 1813 |
+
st.image(cv2.cvtColor(thumbnail, cv2.COLOR_BGR2RGB), width=50)
|
| 1814 |
+
else:
|
| 1815 |
+
st.write("Invalid image")
|
| 1816 |
+
else:
|
| 1817 |
+
st.write("Invalid image")
|
| 1818 |
+
except Exception as e:
|
| 1819 |
+
print(f"Error displaying thumbnail for {row['Name']}: {str(e)}")
|
| 1820 |
+
st.write("Error")
|
| 1821 |
+
else:
|
| 1822 |
+
st.write("No image")
|
| 1823 |
+
|
| 1824 |
with col1:
|
| 1825 |
+
st.write(row["Name"])
|
| 1826 |
with col2:
|
| 1827 |
+
st.write(row["Images"])
|
| 1828 |
with col3:
|
| 1829 |
+
st.write(row["Embeddings"])
|
| 1830 |
with col4:
|
| 1831 |
+
st.write(row["Models"])
|
| 1832 |
with col5:
|
| 1833 |
+
if st.button("Delete", key=f"delete_{row['Name']}"):
|
| 1834 |
+
# Eliminar el registro
|
| 1835 |
+
if row["Name"] in st.session_state.face_database:
|
| 1836 |
+
del st.session_state.face_database[row["Name"]]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1837 |
|
| 1838 |
+
# Guardar la base de datos actualizada
|
| 1839 |
+
if DATABASE_UTILS_AVAILABLE:
|
| 1840 |
+
save_face_database(st.session_state.face_database)
|
| 1841 |
+
|
| 1842 |
+
st.success(f"Deleted {row['Name']} from the database.")
|
| 1843 |
+
st.rerun()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1844 |
|
| 1845 |
+
# Botón para eliminar todos los registros
|
| 1846 |
+
if st.button("Delete All Registered Faces"):
|
| 1847 |
+
# Mostrar confirmación
|
| 1848 |
+
confirm_delete = st.checkbox("Are you sure you want to delete all registered faces? This action cannot be undone.")
|
| 1849 |
+
|
| 1850 |
+
if confirm_delete:
|
| 1851 |
+
# Resetear la base de datos
|
| 1852 |
+
st.session_state.face_database = {}
|
| 1853 |
+
|
| 1854 |
+
# Guardar la base de datos vacía
|
| 1855 |
+
if DATABASE_UTILS_AVAILABLE:
|
| 1856 |
+
save_face_database(st.session_state.face_database)
|
| 1857 |
+
|
| 1858 |
+
st.success("All registered faces have been deleted.")
|
| 1859 |
+
st.rerun()
|
| 1860 |
+
|
| 1861 |
with tab2:
|
| 1862 |
st.header("Image Recognition")
|
| 1863 |
|
|
|
|
| 2235 |
scale_factor = 0.5
|
| 2236 |
h, w = img.shape[:2]
|
| 2237 |
|
| 2238 |
+
small_img = safe_resize(img, (int(w * scale_factor), int(h * scale_factor)))
|
| 2239 |
+
if small_img is None:
|
| 2240 |
+
# Si no se puede redimensionar, usar el frame original (solo para diagnóstico)
|
| 2241 |
+
print("No se pudo redimensionar la imagen para procesamiento")
|
| 2242 |
return av.VideoFrame.from_ndarray(img, format="bgr24")
|
| 2243 |
|
| 2244 |
# Detect faces - la función ahora devuelve directamente los bboxes
|