Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -5,6 +5,183 @@ from PIL import Image
|
|
5 |
import io
|
6 |
from collections import defaultdict
|
7 |
from scipy import ndimage
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
|
9 |
def pre_processar_imagem(imagem):
|
10 |
"""
|
@@ -160,7 +337,10 @@ def analisar_textura_setorial(imagem, iris_info, pupil_info):
|
|
160 |
non_zero = setor_roi[setor_roi != 0]
|
161 |
if len(non_zero) > 0:
|
162 |
# Calcular características de textura
|
163 |
-
|
|
|
|
|
|
|
164 |
|
165 |
setores[f"setor_{i+1}"] = {
|
166 |
"media": np.mean(non_zero),
|
@@ -204,7 +384,10 @@ def analisar_collarette(imagem, iris_info, pupil_info):
|
|
204 |
|
205 |
if len(non_zero) > 0:
|
206 |
# Calcular características
|
207 |
-
|
|
|
|
|
|
|
208 |
|
209 |
return {
|
210 |
"intensidade_media": np.mean(non_zero),
|
@@ -221,7 +404,7 @@ def avaliar_circularidade(mask):
|
|
221 |
"""
|
222 |
Avalia a circularidade de uma região
|
223 |
"""
|
224 |
-
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
225 |
if contours:
|
226 |
cnt = max(contours, key=cv2.contourArea)
|
227 |
area = cv2.contourArea(cnt)
|
@@ -269,17 +452,37 @@ def criar_interface():
|
|
269 |
|
270 |
# Criar visualização
|
271 |
output_img = imagem.copy()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
272 |
|
273 |
# Desenhar esclera
|
274 |
contours, _ = cv2.findContours(mask_esclera, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
275 |
cv2.drawContours(output_img, contours, -1, (255, 255, 0), 1)
|
276 |
|
277 |
# Desenhar íris
|
278 |
-
ix, iy, ir = iris_info
|
279 |
cv2.circle(output_img, (ix, iy), ir, (0, 255, 0), 2)
|
280 |
|
281 |
# Desenhar pupila
|
282 |
-
px, py, pr = pupil_info
|
283 |
cv2.circle(output_img, (px, py), pr, (255, 0, 0), 2)
|
284 |
|
285 |
# Desenhar setores
|
@@ -323,6 +526,10 @@ def criar_interface():
|
|
323 |
if info_collarette['circularidade'] < 0.8:
|
324 |
relatorio += " * Possível deformação estrutural\n"
|
325 |
|
|
|
|
|
|
|
|
|
326 |
return output_img, relatorio
|
327 |
|
328 |
except Exception as e:
|
@@ -332,7 +539,7 @@ def criar_interface():
|
|
332 |
with gr.Blocks(theme=theme, title="Análise Iridológica Avançada") as interface:
|
333 |
gr.Markdown("""
|
334 |
# Sistema Avançado de Análise Iridológica
|
335 |
-
### Detecção precisa de esclera, íris e pupila com análise setorial
|
336 |
""")
|
337 |
|
338 |
with gr.Tabs():
|
|
|
5 |
import io
|
6 |
from collections import defaultdict
|
7 |
from scipy import ndimage
|
8 |
+
from skimage.feature import graycomatrix, graycoprops
|
9 |
+
from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification
|
10 |
+
import torch
|
11 |
+
|
12 |
+
class AnalisadorIridologicoNLP:
|
13 |
+
def __init__(self):
|
14 |
+
# Usando o modelo multilingual BERT para português
|
15 |
+
modelo = "neuralmind/bert-base-portuguese-cased"
|
16 |
+
self.tokenizer = AutoTokenizer.from_pretrained(modelo)
|
17 |
+
self.model = AutoModelForSequenceClassification.from_pretrained(modelo)
|
18 |
+
|
19 |
+
# Dicionário de referência para interpretações
|
20 |
+
self.referencias = {
|
21 |
+
'pupila': {
|
22 |
+
'tamanho': {
|
23 |
+
'grande': 'Indica possível estresse do sistema nervoso ou fadiga adrenal',
|
24 |
+
'pequena': 'Pode indicar tensão nervosa ou hiperatividade',
|
25 |
+
'normal': 'Sistema nervoso em equilíbrio'
|
26 |
+
},
|
27 |
+
'forma': {
|
28 |
+
'irregular': 'Possível desequilíbrio no sistema nervoso autônomo',
|
29 |
+
'regular': 'Boa regulação do sistema nervoso'
|
30 |
+
}
|
31 |
+
},
|
32 |
+
'iris': {
|
33 |
+
'densidade': {
|
34 |
+
'alta': 'Boa integridade do tecido iridiano',
|
35 |
+
'baixa': 'Possível fragilidade tecidual',
|
36 |
+
'media': 'Integridade tecidual normal'
|
37 |
+
},
|
38 |
+
'textura': {
|
39 |
+
'homogenea': 'Tecidos em bom estado',
|
40 |
+
'irregular': 'Possíveis alterações teciduais',
|
41 |
+
'mista': 'Variações na qualidade tecidual'
|
42 |
+
}
|
43 |
+
},
|
44 |
+
'collarette': {
|
45 |
+
'regularidade': {
|
46 |
+
'alta': 'Boa integridade do anel de contração',
|
47 |
+
'baixa': 'Possível comprometimento estrutural',
|
48 |
+
'media': 'Estrutura em condições normais'
|
49 |
+
},
|
50 |
+
'circularidade': {
|
51 |
+
'alta': 'Boa formação estrutural',
|
52 |
+
'baixa': 'Possível alteração na formação',
|
53 |
+
'media': 'Formação estrutural adequada'
|
54 |
+
}
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
def classificar_caracteristica(self, valor, tipo, subtipo):
|
59 |
+
"""
|
60 |
+
Classifica uma característica específica baseada em thresholds
|
61 |
+
"""
|
62 |
+
if tipo == 'pupila':
|
63 |
+
if subtipo == 'tamanho':
|
64 |
+
if valor < 25: return 'pequena'
|
65 |
+
elif valor > 45: return 'grande'
|
66 |
+
else: return 'normal'
|
67 |
+
elif subtipo == 'forma':
|
68 |
+
return 'regular' if valor > 0.85 else 'irregular'
|
69 |
+
|
70 |
+
elif tipo == 'iris':
|
71 |
+
if subtipo == 'densidade':
|
72 |
+
if valor < 0.4: return 'baixa'
|
73 |
+
elif valor > 0.7: return 'alta'
|
74 |
+
else: return 'media'
|
75 |
+
elif subtipo == 'textura':
|
76 |
+
if valor < 0.3: return 'irregular'
|
77 |
+
elif valor > 0.6: return 'homogenea'
|
78 |
+
else: return 'mista'
|
79 |
+
|
80 |
+
elif tipo == 'collarette':
|
81 |
+
if subtipo == 'regularidade':
|
82 |
+
if valor < 300: return 'alta'
|
83 |
+
elif valor > 700: return 'baixa'
|
84 |
+
else: return 'media'
|
85 |
+
elif subtipo == 'circularidade':
|
86 |
+
if valor < 0.7: return 'baixa'
|
87 |
+
elif valor > 0.9: return 'alta'
|
88 |
+
else: return 'media'
|
89 |
+
|
90 |
+
return 'indefinido'
|
91 |
+
|
92 |
+
def gerar_interpretacao(self, metricas):
|
93 |
+
"""
|
94 |
+
Gera uma interpretação em linguagem natural das métricas
|
95 |
+
"""
|
96 |
+
interpretacao = []
|
97 |
+
|
98 |
+
# Análise da pupila
|
99 |
+
if 'pupila' in metricas:
|
100 |
+
tamanho = self.classificar_caracteristica(
|
101 |
+
metricas['pupila']['raio'],
|
102 |
+
'pupila',
|
103 |
+
'tamanho'
|
104 |
+
)
|
105 |
+
forma = self.classificar_caracteristica(
|
106 |
+
metricas['pupila']['circularidade'],
|
107 |
+
'pupila',
|
108 |
+
'forma'
|
109 |
+
)
|
110 |
+
|
111 |
+
interpretacao.append(f"Pupila: {self.referencias['pupila']['tamanho'][tamanho]}")
|
112 |
+
interpretacao.append(f"Forma pupilar: {self.referencias['pupila']['forma'][forma]}")
|
113 |
+
|
114 |
+
# Análise da íris
|
115 |
+
if 'iris' in metricas:
|
116 |
+
densidade = self.classificar_caracteristica(
|
117 |
+
metricas['iris']['densidade_media'],
|
118 |
+
'iris',
|
119 |
+
'densidade'
|
120 |
+
)
|
121 |
+
textura = self.classificar_caracteristica(
|
122 |
+
metricas['iris']['homogeneidade'],
|
123 |
+
'iris',
|
124 |
+
'textura'
|
125 |
+
)
|
126 |
+
|
127 |
+
interpretacao.append(f"Íris: {self.referencias['iris']['densidade'][densidade]}")
|
128 |
+
interpretacao.append(f"Textura: {self.referencias['iris']['textura'][textura]}")
|
129 |
+
|
130 |
+
# Análise do collarette
|
131 |
+
if 'collarette' in metricas:
|
132 |
+
regularidade = self.classificar_caracteristica(
|
133 |
+
metricas['collarette']['regularidade'],
|
134 |
+
'collarette',
|
135 |
+
'regularidade'
|
136 |
+
)
|
137 |
+
circularidade = self.classificar_caracteristica(
|
138 |
+
metricas['collarette']['circularidade'],
|
139 |
+
'collarette',
|
140 |
+
'circularidade'
|
141 |
+
)
|
142 |
+
|
143 |
+
interpretacao.append(f"Collarette: {self.referencias['collarette']['regularidade'][regularidade]}")
|
144 |
+
interpretacao.append(f"Estrutura: {self.referencias['collarette']['circularidade'][circularidade]}")
|
145 |
+
|
146 |
+
# Gerar texto completo
|
147 |
+
texto_interpretacao = "\n".join(interpretacao)
|
148 |
+
|
149 |
+
# Usar o modelo BERT para refinar a linguagem
|
150 |
+
inputs = self.tokenizer(
|
151 |
+
texto_interpretacao,
|
152 |
+
return_tensors="pt",
|
153 |
+
padding=True,
|
154 |
+
truncation=True,
|
155 |
+
max_length=512
|
156 |
+
)
|
157 |
+
|
158 |
+
with torch.no_grad():
|
159 |
+
outputs = self.model(**inputs)
|
160 |
+
refined_text = self.refinar_texto(texto_interpretacao, outputs.logits)
|
161 |
+
|
162 |
+
return refined_text
|
163 |
+
|
164 |
+
def refinar_texto(self, texto, logits):
|
165 |
+
"""
|
166 |
+
Refina o texto usando as logits do modelo
|
167 |
+
"""
|
168 |
+
sentencas = texto.split("\n")
|
169 |
+
refined_sentencas = []
|
170 |
+
|
171 |
+
for sentenca in sentencas:
|
172 |
+
if len(sentenca.strip()) > 0:
|
173 |
+
refined_sentencas.append(f"• {sentenca}")
|
174 |
+
|
175 |
+
return "\n".join(refined_sentencas)
|
176 |
+
|
177 |
+
def integrar_analise_nlp(metricas, analisador=None):
|
178 |
+
"""
|
179 |
+
Integra a análise NLP ao sistema existente
|
180 |
+
"""
|
181 |
+
if analisador is None:
|
182 |
+
analisador = AnalisadorIridologicoNLP()
|
183 |
+
|
184 |
+
return analisador.gerar_interpretacao(metricas)
|
185 |
|
186 |
def pre_processar_imagem(imagem):
|
187 |
"""
|
|
|
337 |
non_zero = setor_roi[setor_roi != 0]
|
338 |
if len(non_zero) > 0:
|
339 |
# Calcular características de textura
|
340 |
+
distances = [1]
|
341 |
+
angles = [0]
|
342 |
+
glcm = graycomatrix(non_zero.reshape(-1, 1), distances, angles,
|
343 |
+
symmetric=True, normed=True)
|
344 |
|
345 |
setores[f"setor_{i+1}"] = {
|
346 |
"media": np.mean(non_zero),
|
|
|
384 |
|
385 |
if len(non_zero) > 0:
|
386 |
# Calcular características
|
387 |
+
distances = [1]
|
388 |
+
angles = [0]
|
389 |
+
glcm = graycomatrix(non_zero.reshape(-1, 1), distances, angles,
|
390 |
+
symmetric=True, normed=True)
|
391 |
|
392 |
return {
|
393 |
"intensidade_media": np.mean(non_zero),
|
|
|
404 |
"""
|
405 |
Avalia a circularidade de uma região
|
406 |
"""
|
407 |
+
contours, _ = cv2.findContours(mask.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
408 |
if contours:
|
409 |
cnt = max(contours, key=cv2.contourArea)
|
410 |
area = cv2.contourArea(cnt)
|
|
|
452 |
|
453 |
# Criar visualização
|
454 |
output_img = imagem.copy()
|
455 |
+
ix, iy, ir = iris_info
|
456 |
+
px, py, pr = pupil_info
|
457 |
+
|
458 |
+
# Criar máscara da pupila para circularidade
|
459 |
+
pupil_mask = np.zeros_like(cv2.cvtColor(imagem, cv2.COLOR_RGB2GRAY))
|
460 |
+
cv2.circle(pupil_mask, (px, py), pr, 255, -1)
|
461 |
+
|
462 |
+
# Preparar métricas para análise NLP
|
463 |
+
metricas = {
|
464 |
+
'pupila': {
|
465 |
+
'raio': pr,
|
466 |
+
'circularidade': avaliar_circularidade(pupil_mask)
|
467 |
+
},
|
468 |
+
'iris': {
|
469 |
+
'densidade_media': np.mean([dados['contraste'] for dados in analise_setorial.values()]),
|
470 |
+
'homogeneidade': np.mean([dados['homogeneidade'] for dados in analise_setorial.values()])
|
471 |
+
},
|
472 |
+
'collarette': info_collarette
|
473 |
+
}
|
474 |
+
|
475 |
+
# Gerar interpretação em linguagem natural
|
476 |
+
interpretacao_nlp = integrar_analise_nlp(metricas)
|
477 |
|
478 |
# Desenhar esclera
|
479 |
contours, _ = cv2.findContours(mask_esclera, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
480 |
cv2.drawContours(output_img, contours, -1, (255, 255, 0), 1)
|
481 |
|
482 |
# Desenhar íris
|
|
|
483 |
cv2.circle(output_img, (ix, iy), ir, (0, 255, 0), 2)
|
484 |
|
485 |
# Desenhar pupila
|
|
|
486 |
cv2.circle(output_img, (px, py), pr, (255, 0, 0), 2)
|
487 |
|
488 |
# Desenhar setores
|
|
|
526 |
if info_collarette['circularidade'] < 0.8:
|
527 |
relatorio += " * Possível deformação estrutural\n"
|
528 |
|
529 |
+
# Adicionar interpretação NLP
|
530 |
+
relatorio += "\n4. INTERPRETAÇÃO EM LINGUAGEM NATURAL\n"
|
531 |
+
relatorio += interpretacao_nlp
|
532 |
+
|
533 |
return output_img, relatorio
|
534 |
|
535 |
except Exception as e:
|
|
|
539 |
with gr.Blocks(theme=theme, title="Análise Iridológica Avançada") as interface:
|
540 |
gr.Markdown("""
|
541 |
# Sistema Avançado de Análise Iridológica
|
542 |
+
### Detecção precisa de esclera, íris e pupila com análise setorial e interpretação em linguagem natural
|
543 |
""")
|
544 |
|
545 |
with gr.Tabs():
|