Spaces:
Runtime error
Runtime error
coder
commited on
Commit
·
551e28c
1
Parent(s):
b8994d7
update onepage
Browse files- Home.py +12 -15
- core/estilos/about_me.css +0 -41
- core/estilos/live_demo.css +0 -81
- core/estilos/teoria.css +0 -81
- core/imagenes/result.png +0 -0
- core/imagenes/shiba.png +0 -0
- pages/Aboutme.py +0 -88
- pages/LiveDemo.py +0 -144
- pages/Teoria.py +0 -216
Home.py
CHANGED
@@ -28,8 +28,6 @@ class Home(Page):
|
|
28 |
def obtener_bytes(self, archivo):
|
29 |
self.set_global(key='img_src',
|
30 |
value=archivo)
|
31 |
-
self.set_global(key='img_bytes',
|
32 |
-
value=archivo.getvalue())
|
33 |
|
34 |
def actualizar_modelo_tokenizer(self, modelo, tokenizer):
|
35 |
self.set_global(key='settings',
|
@@ -40,7 +38,6 @@ class Home(Page):
|
|
40 |
proceso = Generador(configuraciones=self.get_global('settings'))
|
41 |
proceso.generar_prediccion(imagen_bytes=self.imgg.open(
|
42 |
self.get_global('img_src')).convert("RGB"))
|
43 |
-
self.set_global(key='img_output', value=self.get_global('img_bytes'))
|
44 |
self.set_global(key='predicciones', value=proceso.prediccion)
|
45 |
|
46 |
def expander_instrucciones(self, placeholder):
|
@@ -53,12 +50,12 @@ class Home(Page):
|
|
53 |
|
54 |
Elija cualquiera de las dos opciones para cargar su imagen:
|
55 |
|
56 |
-
* **Desde Galería**: cargue la imagen desde la galería de su teléfono o computadora.
|
57 |
|
58 |
-
* **Desde su
|
59 |
|
60 |
|
61 |
-
2. **
|
62 |
|
63 |
Realice la **clasificación de su imagen** con base a las predicciones realizadas por el **modelo** pre-entrenado seleccionado.
|
64 |
|
@@ -78,18 +75,18 @@ class Home(Page):
|
|
78 |
**Cargue su Imagen Base**:
|
79 |
""")
|
80 |
archivo_expander = imagen_base.expander(expanded=False,
|
81 |
-
label="Desde
|
82 |
_archivo = archivo_expander.file_uploader(label="Galería",
|
83 |
accept_multiple_files=False,
|
84 |
label_visibility="visible")
|
85 |
-
if (archivo_expander.button(label="Cargar Archivo",
|
86 |
-
|
87 |
self.obtener_bytes(_archivo)
|
88 |
|
89 |
-
camara_expander = imagen_base.expander(
|
90 |
-
|
91 |
-
_captura = camara_expander.camera_input(
|
92 |
-
|
93 |
if (camara_expander.button(label="Cargar Captura", type="secondary", use_container_width=True,
|
94 |
help="Tome una fotografía.") and _captura is not None):
|
95 |
self.obtener_bytes(_captura)
|
@@ -111,9 +108,9 @@ class Home(Page):
|
|
111 |
def resultados(self, placeholder):
|
112 |
resultados = placeholder.container()
|
113 |
|
114 |
-
if self.get_global('
|
115 |
resultados.image(
|
116 |
-
image=self.get_global('
|
117 |
caption="Su resultado",
|
118 |
use_column_width="auto",
|
119 |
channels="RGB",
|
|
|
28 |
def obtener_bytes(self, archivo):
|
29 |
self.set_global(key='img_src',
|
30 |
value=archivo)
|
|
|
|
|
31 |
|
32 |
def actualizar_modelo_tokenizer(self, modelo, tokenizer):
|
33 |
self.set_global(key='settings',
|
|
|
38 |
proceso = Generador(configuraciones=self.get_global('settings'))
|
39 |
proceso.generar_prediccion(imagen_bytes=self.imgg.open(
|
40 |
self.get_global('img_src')).convert("RGB"))
|
|
|
41 |
self.set_global(key='predicciones', value=proceso.prediccion)
|
42 |
|
43 |
def expander_instrucciones(self, placeholder):
|
|
|
50 |
|
51 |
Elija cualquiera de las dos opciones para cargar su imagen:
|
52 |
|
53 |
+
* **Desde su Galería**: cargue la imagen desde la galería de su teléfono o computadora.
|
54 |
|
55 |
+
* **Desde su Cámara**: cargue la imagen directamente desde la cámara de su teléfono o computadora.
|
56 |
|
57 |
|
58 |
+
2. **Clasificar / Predecir**:
|
59 |
|
60 |
Realice la **clasificación de su imagen** con base a las predicciones realizadas por el **modelo** pre-entrenado seleccionado.
|
61 |
|
|
|
75 |
**Cargue su Imagen Base**:
|
76 |
""")
|
77 |
archivo_expander = imagen_base.expander(expanded=False,
|
78 |
+
label="Desde su Galería")
|
79 |
_archivo = archivo_expander.file_uploader(label="Galería",
|
80 |
accept_multiple_files=False,
|
81 |
label_visibility="visible")
|
82 |
+
if (archivo_expander.button(label="Cargar Archivo", type="secondary", use_container_width=True,
|
83 |
+
help="Suba un archivo.") and _archivo is not None):
|
84 |
self.obtener_bytes(_archivo)
|
85 |
|
86 |
+
camara_expander = imagen_base.expander(expanded=False,
|
87 |
+
label="Desde su Cámara")
|
88 |
+
_captura = camara_expander.camera_input(label="Cámara",
|
89 |
+
label_visibility="visible")
|
90 |
if (camara_expander.button(label="Cargar Captura", type="secondary", use_container_width=True,
|
91 |
help="Tome una fotografía.") and _captura is not None):
|
92 |
self.obtener_bytes(_captura)
|
|
|
108 |
def resultados(self, placeholder):
|
109 |
resultados = placeholder.container()
|
110 |
|
111 |
+
if self.get_global('img_src', None) is not None:
|
112 |
resultados.image(
|
113 |
+
image=self.get_global('img_src').getvalue(),
|
114 |
caption="Su resultado",
|
115 |
use_column_width="auto",
|
116 |
channels="RGB",
|
core/estilos/about_me.css
DELETED
@@ -1,41 +0,0 @@
|
|
1 |
-
/* Estilo Cards */
|
2 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"] {
|
3 |
-
background-color: #070707d1;
|
4 |
-
box-shadow: 1px 1px 2px 2px #000000d2;
|
5 |
-
box-sizing: border-box;
|
6 |
-
padding: 4px 0px 20px 0px;
|
7 |
-
border-radius: 14px;
|
8 |
-
backdrop-filter: blur(4px);
|
9 |
-
transition: ease-out;
|
10 |
-
transition-property: background-color box-shadow transition;
|
11 |
-
transition-duration: 88ms;
|
12 |
-
}
|
13 |
-
|
14 |
-
/* Estilo Cards:Hover*/
|
15 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]:hover {
|
16 |
-
background-color: #070707d0;
|
17 |
-
border: 2px thin;
|
18 |
-
box-shadow: 2px 2px 3px 3px #000000fe;
|
19 |
-
transition: ease-in;
|
20 |
-
transition-property: background-color box-shadow transition;
|
21 |
-
transition-duration: 110ms;
|
22 |
-
}
|
23 |
-
|
24 |
-
|
25 |
-
/* Interno Card: Titulo */
|
26 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="element-container"]>.stHeadingContainer {
|
27 |
-
text-align: center;
|
28 |
-
align-self: center;
|
29 |
-
}
|
30 |
-
|
31 |
-
/* Interno Card: Texto */
|
32 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="element-container"]>.stTextLabelWrapper>[data-testid="stText"] {
|
33 |
-
padding: 0px 8px 0px 8px;
|
34 |
-
}
|
35 |
-
|
36 |
-
/* Interno Card: Row Imágenes */
|
37 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="stHorizontalBlock"] {
|
38 |
-
padding: 0px 8px 0px 8px;
|
39 |
-
}
|
40 |
-
|
41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/estilos/live_demo.css
DELETED
@@ -1,81 +0,0 @@
|
|
1 |
-
/* Estilo Cards */
|
2 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"] {
|
3 |
-
background-color: #070707ef;
|
4 |
-
box-shadow: 1px 1px 2px 2px #000000d2;
|
5 |
-
box-sizing: border-box;
|
6 |
-
padding: 4px 0px 20px 0px;
|
7 |
-
border-radius: 14px;
|
8 |
-
backdrop-filter: blur(4px);
|
9 |
-
transition: ease-out;
|
10 |
-
transition-property: background-color box-shadow transition;
|
11 |
-
transition-duration: 88ms;
|
12 |
-
}
|
13 |
-
|
14 |
-
/* Estilo Cards:Hover*/
|
15 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]:hover {
|
16 |
-
background-color: #070707d0;
|
17 |
-
border: 2px thin;
|
18 |
-
box-shadow: 2px 2px 3px 3px #000000fe;
|
19 |
-
transition: ease-in;
|
20 |
-
transition-property: background-color box-shadow transition;
|
21 |
-
transition-duration: 110ms;
|
22 |
-
}
|
23 |
-
|
24 |
-
|
25 |
-
/* Interno Card: Titulo */
|
26 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="element-container"]>.stHeadingContainer {
|
27 |
-
text-align: center;
|
28 |
-
align-self: center;
|
29 |
-
}
|
30 |
-
|
31 |
-
/* Interno Card: Texto */
|
32 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="element-container"]>.stTextLabelWrapper>[data-testid="stText"] {
|
33 |
-
padding: 0px 8px 0px 8px;
|
34 |
-
}
|
35 |
-
|
36 |
-
/* Interno Card: Markup */
|
37 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="element-container"]>.stMarkdown>[data-testid="stMarkdownContainer"] {
|
38 |
-
padding: 0px 8px 0px 8px;
|
39 |
-
}
|
40 |
-
|
41 |
-
/* Interno Card: Row imagenes */
|
42 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="stHorizontalBlock"] {
|
43 |
-
padding: 0px 8px 0px 8px;
|
44 |
-
display: flex;
|
45 |
-
}
|
46 |
-
|
47 |
-
/* Interno Card: Imágenes */
|
48 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="stHorizontalBlock"]>[data-testid="column"] {
|
49 |
-
display: flex;
|
50 |
-
justify-content: center;
|
51 |
-
align-items: center;
|
52 |
-
}
|
53 |
-
|
54 |
-
/* Interno Card: Botones */
|
55 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="element-container"]>[data-testid="stButton"]>.stTooltipIcon>div>[data-testid="stTooltipIcon"]>[data-testid="tooltipHoverTarget"]{
|
56 |
-
padding: 8px;
|
57 |
-
display: flex;
|
58 |
-
justify-content: center;
|
59 |
-
text-align: center;
|
60 |
-
width: 100%;
|
61 |
-
}
|
62 |
-
|
63 |
-
|
64 |
-
/* Interno Card: Expander */
|
65 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="stExpander"]>ul {
|
66 |
-
background-color: transparent;
|
67 |
-
box-shadow: none;
|
68 |
-
border: none;
|
69 |
-
}
|
70 |
-
|
71 |
-
/* Estilo Expander:Hover*/
|
72 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]:hover {
|
73 |
-
background-color: #070707d0;
|
74 |
-
border: 2px thin;
|
75 |
-
box-shadow: 2px 2px 3px 3px #000000fe;
|
76 |
-
transition: ease-in;
|
77 |
-
transition-property: background-color box-shadow transition;
|
78 |
-
transition-duration: 110ms;
|
79 |
-
}
|
80 |
-
|
81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/estilos/teoria.css
DELETED
@@ -1,81 +0,0 @@
|
|
1 |
-
/* Estilo Cards */
|
2 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"] {
|
3 |
-
background-color: #070707ef;
|
4 |
-
box-shadow: 1px 1px 2px 2px #000000d2;
|
5 |
-
box-sizing: border-box;
|
6 |
-
padding: 4px 0px 20px 0px;
|
7 |
-
border-radius: 14px;
|
8 |
-
backdrop-filter: blur(4px);
|
9 |
-
transition: ease-out;
|
10 |
-
transition-property: background-color box-shadow transition;
|
11 |
-
transition-duration: 88ms;
|
12 |
-
}
|
13 |
-
|
14 |
-
/* Estilo Cards:Hover*/
|
15 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]:hover {
|
16 |
-
background-color: #070707d0;
|
17 |
-
border: 2px thin;
|
18 |
-
box-shadow: 2px 2px 3px 3px #000000fe;
|
19 |
-
transition: ease-in;
|
20 |
-
transition-property: background-color box-shadow transition;
|
21 |
-
transition-duration: 110ms;
|
22 |
-
}
|
23 |
-
|
24 |
-
|
25 |
-
/* Interno Card: Titulo */
|
26 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="element-container"]>.stHeadingContainer {
|
27 |
-
text-align: center;
|
28 |
-
align-self: center;
|
29 |
-
}
|
30 |
-
|
31 |
-
/* Interno Card: Texto */
|
32 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="element-container"]>.stTextLabelWrapper>[data-testid="stText"] {
|
33 |
-
padding: 0px 8px 0px 8px;
|
34 |
-
}
|
35 |
-
|
36 |
-
/* Interno Card: Markup */
|
37 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="element-container"]>.stMarkdown>[data-testid="stMarkdownContainer"] {
|
38 |
-
padding: 0px 8px 0px 8px;
|
39 |
-
}
|
40 |
-
|
41 |
-
/* Interno Card: Row imagenes */
|
42 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="stHorizontalBlock"] {
|
43 |
-
padding: 0px 8px 0px 8px;
|
44 |
-
display: flex;
|
45 |
-
}
|
46 |
-
|
47 |
-
/* Interno Card: Imágenes */
|
48 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="stHorizontalBlock"]>[data-testid="column"] {
|
49 |
-
display: flex;
|
50 |
-
justify-content: center;
|
51 |
-
align-items: center;
|
52 |
-
}
|
53 |
-
|
54 |
-
/* Interno Card: Botones */
|
55 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="element-container"]>[data-testid="stButton"]>.stTooltipIcon>div>[data-testid="stTooltipIcon"]>[data-testid="tooltipHoverTarget"]{
|
56 |
-
padding: 8px;
|
57 |
-
display: flex;
|
58 |
-
justify-content: center;
|
59 |
-
text-align: center;
|
60 |
-
width: 100%;
|
61 |
-
}
|
62 |
-
|
63 |
-
|
64 |
-
/* Interno Card: Expander */
|
65 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]>[data-testid="stExpander"]>ul {
|
66 |
-
background-color: transparent;
|
67 |
-
box-shadow: none;
|
68 |
-
border: none;
|
69 |
-
}
|
70 |
-
|
71 |
-
/* Estilo Expander:Hover*/
|
72 |
-
[data-testid="stVerticalBlock"]>[style*="flex-direction: column;"]>[data-testid="stVerticalBlock"]:hover {
|
73 |
-
background-color: #070707d0;
|
74 |
-
border: 2px thin;
|
75 |
-
box-shadow: 2px 2px 3px 3px #000000fe;
|
76 |
-
transition: ease-in;
|
77 |
-
transition-property: background-color box-shadow transition;
|
78 |
-
transition-duration: 110ms;
|
79 |
-
}
|
80 |
-
|
81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/imagenes/result.png
DELETED
Binary file (12.5 kB)
|
|
core/imagenes/shiba.png
DELETED
Binary file (110 kB)
|
|
pages/Aboutme.py
DELETED
@@ -1,88 +0,0 @@
|
|
1 |
-
from core.controllers.pages_controller import Page
|
2 |
-
from PIL import Image
|
3 |
-
|
4 |
-
|
5 |
-
class AboutMe(Page):
|
6 |
-
variables_globales = {
|
7 |
-
}
|
8 |
-
archivos_css = ["main",
|
9 |
-
"about_me"]
|
10 |
-
|
11 |
-
def __init__(self, title=str("whoami"), icon=str("🖼️"), init_page=False):
|
12 |
-
super().__init__()
|
13 |
-
if init_page:
|
14 |
-
self.new_page(title=title, icon=icon)
|
15 |
-
self.new_body(True)
|
16 |
-
self.init_globals(globals=self.variables_globales)
|
17 |
-
for archivo in self.archivos_css:
|
18 |
-
self.cargar_css(archivo_css=archivo)
|
19 |
-
|
20 |
-
def agregar_card_bienvenido(self, columna):
|
21 |
-
card_bienvenido = columna.container()
|
22 |
-
|
23 |
-
card_bienvenido.header("Sobre la clasificación de imágenes",
|
24 |
-
help=None)
|
25 |
-
card_bienvenido.markdown(unsafe_allow_html=False,
|
26 |
-
help=None,
|
27 |
-
body="""
|
28 |
-
La **clasificación de imágenes en visión artificial** consiste en enseñar a una computadora a **identificar la categoría general de una fotografía**, como "perro" o "coche", en lugar de analizar detalles específicos o ubicar objetos.
|
29 |
-
|
30 |
-
Este **proceso permite a la computadora** reconocer patrones y realizar **predicciones precisas en nuevas imágenes**.
|
31 |
-
""")
|
32 |
-
|
33 |
-
imagen_demo1, imagen_demo2 = card_bienvenido.columns(2, gap="small")
|
34 |
-
src_img_1 = Image.open("core/imagenes/shiba.png")
|
35 |
-
src_img_2 = Image.open("core/imagenes/result.png")
|
36 |
-
imagen_demo1.image(src_img_1,
|
37 |
-
use_column_width="auto")
|
38 |
-
imagen_demo2.image(src_img_2,
|
39 |
-
use_column_width="auto")
|
40 |
-
|
41 |
-
card_bienvenido.markdown(unsafe_allow_html=False,
|
42 |
-
help=None,
|
43 |
-
# Esto se logra mediante el entrenamiento de **algoritmos de aprendizaje profundo**, como las **redes neuronales convolucionales (CNN)** o modelos basados en **Transformers**. Estos algoritmos se entrenan utilizando un **amplio conjunto de datos** de imágenes etiquetadas, donde cada imagen tiene una **etiqueta que describe** su contenido (por ejemplo, "gato" o "árbol").
|
44 |
-
body="""
|
45 |
-
A continuación veremos cómo la librería Transformers utiliza el **modelo pre-entrenado Google/ViT**, entrenado con un conjunto de datos de más de 14 millones de imágenes, etiquetadas en más de 21,000 clases diferentes, todas con una resolución de 224x224.
|
46 |
-
""")
|
47 |
-
|
48 |
-
def agregar_card_teoria(self, columna):
|
49 |
-
card_teoria = columna.container()
|
50 |
-
card_teoria.header("Teoría",
|
51 |
-
help=None)
|
52 |
-
|
53 |
-
def agregar_card_live_demo(self, columna):
|
54 |
-
card_live_demo = columna.container()
|
55 |
-
card_live_demo.header("Demo",
|
56 |
-
help=None)
|
57 |
-
|
58 |
-
def agregar_card_about_me(self, columna):
|
59 |
-
card_about_me = columna.container()
|
60 |
-
card_about_me.header("Desarrollado por:",
|
61 |
-
help=None)
|
62 |
-
card_about_me.subheader("coder160",
|
63 |
-
help=None)
|
64 |
-
|
65 |
-
social1, social2, social3, social4 = card_about_me.columns(
|
66 |
-
4, gap="medium")
|
67 |
-
social1.image("https://imagedelivery.net/5MYSbk45M80qAwecrlKzdQ/8c7c0f2b-5efe-45d3-3041-f6295bd2e600/preview",
|
68 |
-
use_column_width="auto")
|
69 |
-
social2.image("https://imagedelivery.net/5MYSbk45M80qAwecrlKzdQ/8c7c0f2b-5efe-45d3-3041-f6295bd2e600/preview",
|
70 |
-
use_column_width="auto")
|
71 |
-
social3.image("https://imagedelivery.net/5MYSbk45M80qAwecrlKzdQ/8c7c0f2b-5efe-45d3-3041-f6295bd2e600/preview",
|
72 |
-
use_column_width="auto")
|
73 |
-
social4.image("https://imagedelivery.net/5MYSbk45M80qAwecrlKzdQ/8c7c0f2b-5efe-45d3-3041-f6295bd2e600/preview",
|
74 |
-
use_column_width="auto")
|
75 |
-
|
76 |
-
def build(self):
|
77 |
-
# secciones
|
78 |
-
columna_bienvenido, columna_contenido = self.get_body().columns(2, gap="small")
|
79 |
-
seccion_teoria, seccion_live_demo = columna_contenido.columns(
|
80 |
-
2, gap="large")
|
81 |
-
self.agregar_card_bienvenido(columna_bienvenido)
|
82 |
-
self.agregar_card_teoria(seccion_teoria)
|
83 |
-
self.agregar_card_live_demo(seccion_live_demo)
|
84 |
-
self.agregar_card_about_me(columna_contenido)
|
85 |
-
|
86 |
-
|
87 |
-
if __name__ == "__main__":
|
88 |
-
AboutMe(init_page=True).build()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/LiveDemo.py
DELETED
@@ -1,144 +0,0 @@
|
|
1 |
-
from core.controllers.pages_controller import Page
|
2 |
-
from core.controllers.main_process import Generador
|
3 |
-
|
4 |
-
|
5 |
-
class Live_Demo(Page):
|
6 |
-
variables_globales = {
|
7 |
-
"img_bytes": None,
|
8 |
-
"img_src": None,
|
9 |
-
"settings": {
|
10 |
-
"model": str("google/vit-base-patch16-224"),
|
11 |
-
"tokenizer": str("google/vit-base-patch16-224"),
|
12 |
-
},
|
13 |
-
"img_output": None,
|
14 |
-
"predicciones": None,
|
15 |
-
}
|
16 |
-
archivos_css = ["main",
|
17 |
-
"live_demo"]
|
18 |
-
|
19 |
-
def __init__(self, title=str("Live-Demo"), icon=str("🖼️"), init_page=False):
|
20 |
-
super().__init__()
|
21 |
-
if init_page:
|
22 |
-
self.new_page(title=title, icon=icon)
|
23 |
-
self.new_body(True)
|
24 |
-
self.init_globals(globals=self.variables_globales)
|
25 |
-
for archivo in self.archivos_css:
|
26 |
-
self.cargar_css(archivo_css=archivo)
|
27 |
-
|
28 |
-
def obtener_bytes(self, archivo):
|
29 |
-
self.set_global(key='img_src', value=archivo)
|
30 |
-
self.set_global(key='img_bytes', value=archivo.getvalue())
|
31 |
-
|
32 |
-
def actualizar_modelo_tokenizer(self, modelo, tokenizer):
|
33 |
-
_settings = {'model': modelo,
|
34 |
-
'tokenizer': tokenizer}
|
35 |
-
self.set_global(key='settings', value=_settings)
|
36 |
-
|
37 |
-
def procesar_imagen(self):
|
38 |
-
proceso = Generador(configuraciones=self.get_global('settings'))
|
39 |
-
proceso.generar_prediccion(imagen_bytes=self.imgg.open(self.get_global('img_src')).convert("RGB"))
|
40 |
-
self.set_global(key='img_output', value=self.get_global('img_bytes'))
|
41 |
-
self.set_global(key='predicciones', value=proceso.prediccion)
|
42 |
-
|
43 |
-
def archivo_expander(self, section):
|
44 |
-
archivo_expander = section.expander(
|
45 |
-
expanded=False,
|
46 |
-
label="Desde su galería"
|
47 |
-
)
|
48 |
-
_archivo = archivo_expander.file_uploader(
|
49 |
-
label="GALERIA",
|
50 |
-
accept_multiple_files=False,
|
51 |
-
label_visibility="visible"
|
52 |
-
)
|
53 |
-
if (archivo_expander.button(label="Cargar Archivo", help="Suba un archivo.",
|
54 |
-
type="secondary", use_container_width=True) and _archivo is not None):
|
55 |
-
self.obtener_bytes(_archivo)
|
56 |
-
|
57 |
-
def camara_expander(self, section):
|
58 |
-
camara_expander = section.expander(
|
59 |
-
expanded=False,
|
60 |
-
label="Desde su cámara"
|
61 |
-
)
|
62 |
-
_captura = camara_expander.camera_input(
|
63 |
-
label="CAMARA",
|
64 |
-
label_visibility="visible"
|
65 |
-
)
|
66 |
-
if (camara_expander.button(label="Cargar Captura", help="Tome una fotografía.",
|
67 |
-
type="secondary", use_container_width=True) and _captura is not None):
|
68 |
-
self.obtener_bytes(_captura)
|
69 |
-
|
70 |
-
def preview_expander(self, section):
|
71 |
-
preview = section.expander(
|
72 |
-
expanded=True,
|
73 |
-
label="Todo listo"
|
74 |
-
)
|
75 |
-
if self.get_global('img_bytes', None) is not None:
|
76 |
-
preview.image(
|
77 |
-
image=self.get_global('img_bytes'),
|
78 |
-
caption="Su imagen",
|
79 |
-
use_column_width="auto",
|
80 |
-
channels="RGB",
|
81 |
-
output_format="auto"
|
82 |
-
)
|
83 |
-
if preview.button(label="LAUNCH", help="Procesar imagen",
|
84 |
-
type="secondary", use_container_width=True):
|
85 |
-
self.procesar_imagen()
|
86 |
-
|
87 |
-
def config_expander(self, section):
|
88 |
-
modelo = section.text_input(
|
89 |
-
label="MODELO",
|
90 |
-
value=self.get_global('settings').get('model'),
|
91 |
-
key=None,
|
92 |
-
help=None,
|
93 |
-
on_change=None,
|
94 |
-
disabled=False,
|
95 |
-
label_visibility="visible"
|
96 |
-
)
|
97 |
-
tokenizer = section.text_input(
|
98 |
-
label="TOKENIZER",
|
99 |
-
value=self.get_global('settings').get('tokenizer'),
|
100 |
-
key=None,
|
101 |
-
help=None,
|
102 |
-
on_change=None,
|
103 |
-
disabled=False,
|
104 |
-
label_visibility="visible"
|
105 |
-
)
|
106 |
-
if section.button(label="Configurar", help="Actualice configuraciones",
|
107 |
-
type="secondary", use_container_width=True):
|
108 |
-
self.actualizar_modelo_tokenizer(modelo, tokenizer)
|
109 |
-
|
110 |
-
def agregar_card_inputs(self, columna):
|
111 |
-
card_inputs = columna.container()
|
112 |
-
source_tab, config_tab = card_inputs.tabs(
|
113 |
-
["Imagen", "Configuraciones"]
|
114 |
-
)
|
115 |
-
self.archivo_expander(source_tab)
|
116 |
-
self.camara_expander(source_tab)
|
117 |
-
self.config_expander(config_tab)
|
118 |
-
self.preview_expander(card_inputs)
|
119 |
-
|
120 |
-
def agregar_card_outputs(self, columna):
|
121 |
-
card_teoria = columna.container()
|
122 |
-
result_tab, process_tab = card_teoria.tabs(
|
123 |
-
["Resultado", "Proceso"]
|
124 |
-
)
|
125 |
-
if self.get_global('img_output', None) is not None:
|
126 |
-
result_tab.image(
|
127 |
-
image=self.get_global('img_output'),
|
128 |
-
caption="Su resultado",
|
129 |
-
use_column_width="auto",
|
130 |
-
channels="RGB",
|
131 |
-
output_format="auto"
|
132 |
-
)
|
133 |
-
if self.get_global('predicciones', None) is not None:
|
134 |
-
result_tab.success(body=self.get_global('predicciones'), icon=None)
|
135 |
-
|
136 |
-
def build(self):
|
137 |
-
# secciones
|
138 |
-
columna_inputs, columna_outputs = self.get_body().columns(2, gap="small")
|
139 |
-
self.agregar_card_inputs(columna_inputs)
|
140 |
-
self.agregar_card_outputs(columna_outputs)
|
141 |
-
|
142 |
-
|
143 |
-
if __name__ == "__main__":
|
144 |
-
Live_Demo(init_page=True).build()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/Teoria.py
DELETED
@@ -1,216 +0,0 @@
|
|
1 |
-
from core.controllers.pages_controller import Page
|
2 |
-
|
3 |
-
|
4 |
-
class Teoria(Page):
|
5 |
-
variables_globales = {
|
6 |
-
}
|
7 |
-
archivos_css = ["main",
|
8 |
-
"teoria"]
|
9 |
-
avances = [
|
10 |
-
{"fecha": 1960,
|
11 |
-
"texto": "Aparece 1"},
|
12 |
-
{"fecha": 1970,
|
13 |
-
"texto": "Aparece 2"},
|
14 |
-
{"fecha": 1980,
|
15 |
-
"texto": "Aparece 3"},
|
16 |
-
{"fecha": 1990,
|
17 |
-
"texto": "Aparece 4"},
|
18 |
-
{"fecha": 2000,
|
19 |
-
"texto": "Aparece 5"},
|
20 |
-
{"fecha": 2010,
|
21 |
-
"texto": "Aparece 6"},
|
22 |
-
{"fecha": 2020,
|
23 |
-
"texto": "Aparece 7"}
|
24 |
-
]
|
25 |
-
fuentes = [
|
26 |
-
{"titulo": "Analysis of Classification by Supervised and Unsupervised Learning",
|
27 |
-
"url": "https://www.computer.org/csdl/proceedings-article/iccima/2007/30500280/12OmNzxyiHV"},
|
28 |
-
{"titulo": "Implementation of Interval Arithmetic Algorithms on FPGAs",
|
29 |
-
"url": "https://dl.acm.org/doi/10.1109/ICCIMA.2007.237"},
|
30 |
-
{"titulo": "La Noticia 3",
|
31 |
-
"url": "https://enlace3.com"},
|
32 |
-
{"titulo": "La Noticia 4",
|
33 |
-
"url": "https://enlace4.com"},
|
34 |
-
{"titulo": "La Noticia 5",
|
35 |
-
"url": "https://enlac5.com"},
|
36 |
-
{"titulo": "La Noticia 6",
|
37 |
-
"url": "https://enlace6.com"},
|
38 |
-
]
|
39 |
-
|
40 |
-
def __init__(self, title=str("Teoría"), icon=str("🖼️"), init_page=False):
|
41 |
-
super().__init__()
|
42 |
-
if init_page:
|
43 |
-
self.new_page(title=title, icon=icon)
|
44 |
-
self.new_body(True)
|
45 |
-
self.init_globals(globals=self.variables_globales)
|
46 |
-
for archivo in self.archivos_css:
|
47 |
-
self.cargar_css(archivo_css=archivo)
|
48 |
-
|
49 |
-
def agregar_card_fundamentos(self, columna):
|
50 |
-
card_fundamentos = columna.container()
|
51 |
-
card_fundamentos.markdown(
|
52 |
-
unsafe_allow_html=False,
|
53 |
-
help=None,
|
54 |
-
body="""
|
55 |
-
## Sobre el origen de la tecnología
|
56 |
-
""")
|
57 |
-
expander = card_fundamentos.expander(
|
58 |
-
expanded=False,
|
59 |
-
label="Aspectos básicos y fundamentales de la clasificación de imágenes."
|
60 |
-
)
|
61 |
-
expander.markdown(
|
62 |
-
unsafe_allow_html=False,
|
63 |
-
help=None,
|
64 |
-
body="""
|
65 |
-
La **visión artificial** es un **campo interdisciplinario** que busca **emular la percepción visual humana** utilizando **sistemas computacionales**.
|
66 |
-
|
67 |
-
La **clasificación de imágenes**, es una rama esencial de la **visión artificial**, se refiere a la **capacidad de las computadoras** para **identificar y categorizar** objetos y patrones en **imágenes visuales.**
|
68 |
-
""")
|
69 |
-
imagen_intro1, imagen_intro2, imagen_intro3 = expander.columns(
|
70 |
-
3, gap="small")
|
71 |
-
src_imgI_1 = self.imgg.open("core/imagenes/shiba.png")
|
72 |
-
src_imgI_2 = self.imgg.open("core/imagenes/shiba.png")
|
73 |
-
src_imgI_3 = self.imgg.open("core/imagenes/shiba.png")
|
74 |
-
imagen_intro1.image(
|
75 |
-
src_imgI_1,
|
76 |
-
use_column_width="auto"
|
77 |
-
)
|
78 |
-
imagen_intro2.image(
|
79 |
-
src_imgI_2,
|
80 |
-
use_column_width="auto"
|
81 |
-
)
|
82 |
-
imagen_intro3.image(
|
83 |
-
src_imgI_3,
|
84 |
-
use_column_width="auto"
|
85 |
-
)
|
86 |
-
expander.markdown(
|
87 |
-
unsafe_allow_html=False,
|
88 |
-
help=None,
|
89 |
-
body="""
|
90 |
-
La **clasificación de imágenes** tuvo sus inicios en las **décadas de 1960 y 1970**, cuando los **investigadores** comenzaron a explorar **métodos** para la **detección** de bordes y formas elementales en **imágenes** [Roberts, 1973]. Fue en este **período** cuando se sentaron las **bases** para la **comprensión** computacional del **contenido visual**.
|
91 |
-
|
92 |
-
Las **primeras aplicaciones** de la **clasificación de imágenes** se centraron en la **detección y reconocimiento** de patrones básicos en **imágenes**, con **aplicaciones** en campos como la **industria manufacturera** y la **inspección de calidad**.
|
93 |
-
|
94 |
-
A lo largo de su **evolución**, la **clasificación de imágenes** por computadora ha experimentado **avances** notables.
|
95 |
-
""")
|
96 |
-
imagen_outro1, imagen_outro2 = expander.columns(2, gap="small")
|
97 |
-
src_imgO_1 = self.imgg.open("core/imagenes/shiba.png")
|
98 |
-
src_imgO_2 = self.imgg.open("core/imagenes/shiba.png")
|
99 |
-
imagen_outro1.image(
|
100 |
-
src_imgO_1,
|
101 |
-
use_column_width="auto"
|
102 |
-
)
|
103 |
-
imagen_outro2.image(
|
104 |
-
src_imgO_2,
|
105 |
-
use_column_width="auto"
|
106 |
-
)
|
107 |
-
expander.markdown(
|
108 |
-
unsafe_allow_html=False,
|
109 |
-
help=None,
|
110 |
-
body="""
|
111 |
-
Desde su **descubrimiento** en la década de **1960**, la introducción de **redes neuronales convolucionales** (CNN) en los **90's**, incluyendo la última década, marcada por la adopción de **modelos** pre-entrenados con **transformers**, como el **Vision Transformer** (ViT) en **2021** y el **Swin Transformer** en el mismo año, se ha presenciado una **transición significativa** en la **capacidad** de las **computadoras** para **comprender y categorizar contenido visual**, impulsando la **visión artificial** hacia nuevas fronteras de **eficiencia y precisión** en la **clasificación de imágenes**.
|
112 |
-
""")
|
113 |
-
card_fundamentos.markdown(
|
114 |
-
unsafe_allow_html=False,
|
115 |
-
help=None,
|
116 |
-
body="""
|
117 |
-
##### La **clasificación de imágenes**, esencial en **visión artificial**, implica que las **computadoras identifiquen objetos en imágenes.**
|
118 |
-
""")
|
119 |
-
|
120 |
-
def agregar_card_avances(self, columna):
|
121 |
-
card_avances = columna.container()
|
122 |
-
|
123 |
-
card_avances.markdown(
|
124 |
-
unsafe_allow_html=False,
|
125 |
-
help=None,
|
126 |
-
body="""
|
127 |
-
## Línea de tiempo.
|
128 |
-
""")
|
129 |
-
expander = card_avances.expander(
|
130 |
-
expanded=False,
|
131 |
-
label="Avances, desarrollos y aplicaciones a través de la historia."
|
132 |
-
)
|
133 |
-
expander.markdown(
|
134 |
-
unsafe_allow_html=False,
|
135 |
-
help=None,
|
136 |
-
body="""
|
137 |
-
Desde la **década de 1960** hasta la **actualidad**, la **clasificación de imágenes** por **visión artificial** ha tenido **grandes avances**.
|
138 |
-
|
139 |
-
A continuación puede **ver** de forma **interactiva** algunos de estos **avances**.
|
140 |
-
""")
|
141 |
-
a_inicio, a_fin = expander.select_slider(
|
142 |
-
label='Seleccione un rango de fecha',
|
143 |
-
options=[avance.get('fecha') for avance in self.avances],
|
144 |
-
value=(self.avances[1].get('fecha'), self.avances[2].get('fecha')))
|
145 |
-
expander.markdown(
|
146 |
-
unsafe_allow_html=False,
|
147 |
-
help=None,
|
148 |
-
body=f"""
|
149 |
-
##### Algunos acontecimientos desde {a_inicio} hasta {a_fin} incluyen:
|
150 |
-
"""
|
151 |
-
)
|
152 |
-
for fecha in range(a_inicio, a_fin+1):
|
153 |
-
for avance in self.avances:
|
154 |
-
if fecha == avance.get('fecha'):
|
155 |
-
expander.markdown(
|
156 |
-
unsafe_allow_html=False,
|
157 |
-
help=None,
|
158 |
-
body=f"""
|
159 |
-
###### **{avance.get('fecha')}** : *{avance.get('texto')}*
|
160 |
-
"""
|
161 |
-
)
|
162 |
-
card_avances.markdown(
|
163 |
-
unsafe_allow_html=False,
|
164 |
-
help=None,
|
165 |
-
# Esto se logra mediante el entrenamiento de **algoritmos de aprendizaje profundo**, como las **redes neuronales convolucionales (CNN)** o modelos basados en **Transformers**. Estos algoritmos se entrenan utilizando un **amplio conjunto de datos** de imágenes etiquetadas, donde cada imagen tiene una **etiqueta que describe** su contenido (por ejemplo, "gato" o "árbol").
|
166 |
-
# A continuación veremos cómo la librería Transformers utiliza el **modelo pre-entrenado Google/ViT**, entrenado con un conjunto de datos de más de 14 millones de imágenes, etiquetadas en más de 21,000 clases diferentes, todas con una resolución de 224x224.
|
167 |
-
body="""
|
168 |
-
##### Desde sus **orígenes** hasta la **actualidad**, la **clasificación de imágenes** ha tenido **grandes avances** en el campo de la **automatización e inteligencia artificial**.
|
169 |
-
|
170 |
-
""")
|
171 |
-
|
172 |
-
def agregar_card_fuentes(self, columna):
|
173 |
-
card_fuentes = columna.container()
|
174 |
-
card_fuentes.markdown(
|
175 |
-
unsafe_allow_html=False,
|
176 |
-
help=None,
|
177 |
-
body="""
|
178 |
-
## Fuentes
|
179 |
-
""")
|
180 |
-
expander = card_fuentes.expander(
|
181 |
-
expanded=False,
|
182 |
-
label="Enlaces de referencia."
|
183 |
-
)
|
184 |
-
|
185 |
-
for fuente in self.fuentes:
|
186 |
-
expander.markdown(
|
187 |
-
unsafe_allow_html=False,
|
188 |
-
help=None,
|
189 |
-
body=f"""
|
190 |
-
###### * **{fuente.get('titulo')}:**
|
191 |
-
|
192 |
-
*Enlace: {fuente.get('url')}*
|
193 |
-
"""
|
194 |
-
)
|
195 |
-
card_fuentes.markdown(
|
196 |
-
unsafe_allow_html=False,
|
197 |
-
help=None,
|
198 |
-
body="""
|
199 |
-
###### Es **importante** mencionar que esta **compilación** se encuentra en proceso de **construcción**.
|
200 |
-
|
201 |
-
*Si deseas **participar**, eres **bienvenido** de aportar en el repositorio oficial:*
|
202 |
-
|
203 |
-
https://github.com/coder160/demos/
|
204 |
-
""")
|
205 |
-
|
206 |
-
def build(self):
|
207 |
-
# secciones
|
208 |
-
columna_principal = self.get_body().columns(1, gap="small")[0]
|
209 |
-
|
210 |
-
self.agregar_card_fundamentos(columna_principal)
|
211 |
-
self.agregar_card_avances(columna_principal)
|
212 |
-
self.agregar_card_fuentes(columna_principal)
|
213 |
-
|
214 |
-
|
215 |
-
if __name__ == "__main__":
|
216 |
-
Teoria(init_page=True).build()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|