DHEIVER commited on
Commit
5a2b86b
·
verified ·
1 Parent(s): 564252c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +216 -218
app.py CHANGED
@@ -5,221 +5,192 @@ from PIL import Image
5
  import io
6
  from collections import defaultdict
7
 
8
- def detectar_iris(imagem):
9
  """
10
- Detecta a íris na imagem e retorna a região de interesse
11
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  # Converter para escala de cinza
13
- gray = cv2.cvtColor(imagem, cv2.COLOR_RGB2GRAY)
14
 
15
  # Aplicar blur para reduzir ruído
16
  blur = cv2.GaussianBlur(gray, (7, 7), 0)
17
 
18
- # Detectar círculos (íris) usando transformada de Hough
19
- circles = cv2.HoughCircles(
20
- blur,
 
 
 
 
 
 
 
21
  cv2.HOUGH_GRADIENT,
22
  dp=1,
23
  minDist=50,
24
  param1=50,
 
 
 
 
 
 
 
 
 
 
 
 
25
  param2=30,
26
- minRadius=50,
27
  maxRadius=150
28
  )
29
 
30
- if circles is not None:
31
- # Converter coordenadas para inteiros
32
- circles = np.uint16(np.around(circles))
33
-
34
- # Pegar o primeiro círculo detectado
35
- x, y, r = circles[0][0]
36
-
37
- # Criar máscara circular
38
- mask = np.zeros_like(gray)
39
- cv2.circle(mask, (x, y), r, 255, -1)
40
-
41
- # Aplicar máscara na imagem original
42
- result = cv2.bitwise_and(imagem, imagem, mask=mask)
43
-
44
- # Recortar região da íris
45
- roi = result[y-r:y+r, x-r:x+r]
46
-
47
- return roi, (x, y, r)
48
-
49
- return None, None
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
- def analisar_textura(roi):
52
  """
53
- Analisa a textura da íris para identificar padrões
54
  """
55
- if roi is None:
56
  return {}
57
 
58
  # Converter para escala de cinza
59
- gray = cv2.cvtColor(roi, cv2.COLOR_RGB2GRAY)
60
-
61
- # Análises de textura
62
- padroes = {
63
- "congestao_inflamacao": False,
64
- "deficiencia_hipofuncao": False,
65
- "atrofia_degeneracao": False,
66
- "irritacao_estresse": False
67
- }
68
-
69
- # Análise de variância local
70
- kernel_size = 5
71
- local_var = cv2.Laplacian(gray, cv2.CV_64F).var()
72
-
73
- # Análise de intensidade média
74
- mean_intensity = np.mean(gray)
75
-
76
- # Análise de contraste
77
- contrast = np.std(gray)
78
-
79
- # Detecção de bordas
80
- edges = cv2.Canny(gray, 100, 200)
81
- edge_density = np.sum(edges) / (edges.shape[0] * edges.shape[1])
82
-
83
- # Definir limiares para cada padrão
84
- if local_var > 100:
85
- padroes["congestao_inflamacao"] = True
86
 
87
- if mean_intensity < 100:
88
- padroes["deficiencia_hipofuncao"] = True
 
89
 
90
- if contrast < 30:
91
- padroes["atrofia_degeneracao"] = True
 
 
92
 
93
- if edge_density > 0.1:
94
- padroes["irritacao_estresse"] = True
95
 
96
- return padroes
97
-
98
- def analisar_setores(roi, centro, raio):
99
- """
100
- Analisa diferentes setores da íris
101
- """
102
- if roi is None:
103
- return {}
104
 
 
105
  setores = {
106
- "superior": (315, 45), # Cérebro
107
- "direito": (45, 135), # Fígado
108
- "inferior": (135, 225), # Sistema Digestivo
109
- "esquerdo": (225, 315) # Coração
110
  }
111
 
112
- resultados = {}
113
-
114
  for setor, (ang_inicio, ang_fim) in setores.items():
115
- # Criar máscara para o setor
116
- mask = np.zeros_like(roi[:,:,0])
117
- cv2.ellipse(mask,
118
- (raio, raio),
119
- (raio-10, raio-10),
120
- 0,
121
- ang_inicio,
122
- ang_fim,
123
- 255,
124
  -1)
125
 
126
- # Aplicar máscara
127
- setor_roi = cv2.bitwise_and(roi, roi, mask=mask)
128
 
129
- # Analisar textura do setor
130
- resultados[setor] = analisar_textura(setor_roi)
131
-
132
- return resultados
 
 
 
 
 
 
 
133
 
134
- def gerar_diagnostico(padroes, setores):
135
  """
136
- Gera diagnóstico baseado nos padrões encontrados
137
  """
138
- diagnostico = []
139
-
140
- # Mapeamento de padrões para possíveis condições
141
- mapa_condicoes = {
142
- "congestao_inflamacao": [
143
- "Processo inflamatório ativo",
144
- "Possível condição autoimune",
145
- "Inflamação crônica"
146
- ],
147
- "deficiencia_hipofuncao": [
148
- "Deficiência nutricional",
149
- "Hipofunção glandular",
150
- "Fadiga crônica"
151
- ],
152
- "atrofia_degeneracao": [
153
- "Desgaste tecidual",
154
- "Processo degenerativo",
155
- "Envelhecimento acelerado"
156
- ],
157
- "irritacao_estresse": [
158
- "Estresse crônico",
159
- "Sobrecarga do sistema nervoso",
160
- "Ansiedade"
161
- ]
162
- }
163
 
164
- # Analisar padrões gerais
165
- for padrao, presente in padroes.items():
166
- if presente:
167
- diagnostico.extend(mapa_condicoes[padrao])
168
 
169
- # Analisar setores específicos
170
- for setor, padroes_setor in setores.items():
171
- for padrao, presente in padroes_setor.items():
172
- if presente:
173
- if setor == "superior":
174
- diagnostico.append(f"Região cerebral: {mapa_condicoes[padrao][0]}")
175
- elif setor == "direito":
176
- diagnostico.append(f"Região hepática: {mapa_condicoes[padrao][0]}")
177
- elif setor == "inferior":
178
- diagnostico.append(f"Região digestiva: {mapa_condicoes[padrao][0]}")
179
- elif setor == "esquerdo":
180
- diagnostico.append(f"Região cardíaca: {mapa_condicoes[padrao][0]}")
181
 
182
- return list(set(diagnostico)) # Remover duplicatas
183
-
184
- def processar_imagem(imagem):
185
- """
186
- Processa a imagem da íris e retorna análise
187
- """
188
- # Converter imagem para formato OpenCV
189
- img_array = np.array(imagem)
190
 
191
- # Detectar íris
192
- roi, (x, y, r) = detectar_iris(img_array)
193
- if roi is None:
194
- return "Não foi possível detectar a íris na imagem."
195
 
196
- # Analisar padrões gerais
197
- padroes = analisar_textura(roi)
 
198
 
199
- # Analisar setores
200
- setores = analisar_setores(roi, (x, y), r)
 
 
 
 
201
 
202
- # Gerar diagnóstico
203
- diagnostico = gerar_diagnostico(padroes, setores)
204
-
205
- # Gerar visualização
206
- output_img = img_array.copy()
207
- cv2.circle(output_img, (x, y), r, (0, 255, 0), 2)
208
-
209
- # Desenhar setores
210
- ang_step = 45
211
- for ang in range(0, 360, ang_step):
212
- end_x = int(x + r * np.cos(np.radians(ang)))
213
- end_y = int(y + r * np.sin(np.radians(ang)))
214
- cv2.line(output_img, (x, y), (end_x, end_y), (0, 255, 0), 1)
215
-
216
- return output_img, "\n".join(diagnostico)
217
 
218
  def criar_interface():
219
  """
220
- Cria interface moderna do Gradio
221
  """
222
- # Tema personalizado verde piscina
223
  theme = gr.themes.Soft(
224
  primary_hue="teal",
225
  secondary_hue="green",
@@ -232,11 +203,62 @@ def criar_interface():
232
  button_primary_background_fill_dark="#264653",
233
  )
234
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  # Interface
236
- with gr.Blocks(theme=theme, title="Análise Iridológica por Imagem") as interface:
237
  gr.Markdown("""
238
  # Sistema Avançado de Análise Iridológica
239
- ### Análise automatizada de imagens da íris
240
  """)
241
 
242
  with gr.Tabs():
@@ -246,17 +268,17 @@ def criar_interface():
246
  with gr.Column():
247
  input_image = gr.Image(
248
  label="Imagem da Íris",
249
- type="pil"
250
  )
251
  with gr.Column():
252
  output_image = gr.Image(
253
- label="Íris Analisada"
254
  )
255
 
256
  analysis_btn = gr.Button("Analisar Íris", variant="primary")
257
  output_text = gr.Textbox(
258
- label="Diagnóstico",
259
- lines=10
260
  )
261
 
262
  analysis_btn.click(
@@ -265,56 +287,32 @@ def criar_interface():
265
  outputs=[output_image, output_text]
266
  )
267
 
268
- # Aba de Guia
269
- with gr.Tab("Guia de Interpretação"):
270
  gr.Markdown("""
271
- ## Interpretação dos Sinais
272
-
273
- ### Padrões Principais
274
- - **Congestão/Inflamação**: Áreas escuras ou densas
275
- - **Deficiência/Hipofunção**: Áreas claras ou vazias
276
- - **Atrofia/Degeneração**: Lacunas ou descontinuidades
277
- - **Irritação/Estresse**: Linhas radiais ou manchas
278
 
279
- ### Setores da Íris
280
- 1. **Superior**: Região cerebral
281
- 2. **Direito**: Região hepática
282
- 3. **Inferior**: Região digestiva
283
- 4. **Esquerdo**: Região cardíaca
284
-
285
- ### Recomendações
286
- - Faça a foto com boa iluminação
287
- - Mantenha o olho bem aberto
288
- - Evite reflexos na imagem
289
- - Use câmera com boa resolução
290
- """)
291
-
292
- # Aba de Recomendações
293
- with gr.Tab("Recomendações"):
294
- gr.Markdown("""
295
- ## Recomendações Gerais
296
-
297
- ### Qualidade da Imagem
298
- - Resolução mínima: 1280x720
299
- - Iluminação uniforme
300
- - Foco na íris
301
- - Sem reflexos
302
-
303
- ### Preparação
304
- 1. **Ambiente**
305
- - Bem iluminado
306
- - Sem luz direta
307
- - Fundo claro
308
 
309
  2. **Posicionamento**
310
  - Olho bem aberto
311
- - Câmera estável
312
- - Distância adequada
 
 
 
 
 
313
 
314
- 3. **Momento**
315
- - Evite olhos irritados
316
- - Preferencialmente pela manhã
317
- - Após descanso
 
318
  """)
319
 
320
  return interface
 
5
  import io
6
  from collections import defaultdict
7
 
8
+ def melhorar_contraste(imagem):
9
  """
10
+ Aplica equalização de histograma adaptativo para melhorar contraste
11
  """
12
+ lab = cv2.cvtColor(imagem, cv2.COLOR_RGB2LAB)
13
+ l, a, b = cv2.split(lab)
14
+ clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
15
+ l = clahe.apply(l)
16
+ lab = cv2.merge((l,a,b))
17
+ return cv2.cvtColor(lab, cv2.COLOR_LAB2RGB)
18
+
19
+ def detectar_pupila_iris(imagem):
20
+ """
21
+ Detecta pupila e íris com técnicas avançadas
22
+ """
23
+ # Melhorar contraste
24
+ imagem_melhorada = melhorar_contraste(imagem)
25
+
26
  # Converter para escala de cinza
27
+ gray = cv2.cvtColor(imagem_melhorada, cv2.COLOR_RGB2GRAY)
28
 
29
  # Aplicar blur para reduzir ruído
30
  blur = cv2.GaussianBlur(gray, (7, 7), 0)
31
 
32
+ # Detectar bordas
33
+ edges = cv2.Canny(blur, 30, 60)
34
+
35
+ # Aplicar fechamento morfológico para conectar bordas
36
+ kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
37
+ closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
38
+
39
+ # Detectar círculos para pupila (menores)
40
+ pupila_circles = cv2.HoughCircles(
41
+ closed,
42
  cv2.HOUGH_GRADIENT,
43
  dp=1,
44
  minDist=50,
45
  param1=50,
46
+ param2=25,
47
+ minRadius=20,
48
+ maxRadius=50
49
+ )
50
+
51
+ # Detectar círculos para íris (maiores)
52
+ iris_circles = cv2.HoughCircles(
53
+ closed,
54
+ cv2.HOUGH_GRADIENT,
55
+ dp=1,
56
+ minDist=100,
57
+ param1=50,
58
  param2=30,
59
+ minRadius=80,
60
  maxRadius=150
61
  )
62
 
63
+ output_img = imagem.copy()
64
+
65
+ # Desenhar círculos da pupila
66
+ if pupila_circles is not None:
67
+ pupila_circles = np.uint16(np.around(pupila_circles))
68
+ for i in pupila_circles[0,:]:
69
+ # Desenhar círculo da pupila
70
+ cv2.circle(output_img, (i[0], i[1]), i[2], (255, 0, 0), 2)
71
+ # Desenhar centro
72
+ cv2.circle(output_img, (i[0], i[1]), 2, (0, 0, 255), 3)
73
+ pupila_info = (i[0], i[1], i[2])
74
+ else:
75
+ pupila_info = None
76
+
77
+ # Desenhar círculos da íris
78
+ if iris_circles is not None:
79
+ iris_circles = np.uint16(np.around(iris_circles))
80
+ for i in iris_circles[0,:]:
81
+ # Desenhar círculo da íris
82
+ cv2.circle(output_img, (i[0], i[1]), i[2], (0, 255, 0), 2)
83
+ iris_info = (i[0], i[1], i[2])
84
+
85
+ # Desenhar setores da íris
86
+ ang_step = 45
87
+ for ang in range(0, 360, ang_step):
88
+ end_x = int(i[0] + i[2] * np.cos(np.radians(ang)))
89
+ end_y = int(i[1] + i[2] * np.sin(np.radians(ang)))
90
+ cv2.line(output_img, (i[0], i[1]), (end_x, end_y), (0, 255, 0), 1)
91
+ else:
92
+ iris_info = None
93
+
94
+ return output_img, pupila_info, iris_info
95
 
96
+ def extrair_caracteristicas_avancadas(imagem, pupila_info, iris_info):
97
  """
98
+ Extrai características avançadas da íris usando a posição da pupila
99
  """
100
+ if pupila_info is None or iris_info is None:
101
  return {}
102
 
103
  # Converter para escala de cinza
104
+ gray = cv2.cvtColor(imagem, cv2.COLOR_RGB2GRAY)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
 
106
+ # Coordenadas da pupila e íris
107
+ px, py, pr = pupila_info
108
+ ix, iy, ir = iris_info
109
 
110
+ # Criar máscara anelar (região entre pupila e íris)
111
+ mask = np.zeros_like(gray)
112
+ cv2.circle(mask, (ix, iy), ir, 255, -1) # Íris
113
+ cv2.circle(mask, (px, py), pr, 0, -1) # Pupila
114
 
115
+ # Aplicar máscara
116
+ iris_ring = cv2.bitwise_and(gray, gray, mask=mask)
117
 
118
+ # Análise de textura
119
+ caracteristicas = {}
 
 
 
 
 
 
120
 
121
+ # Divisão em setores
122
  setores = {
123
+ "superior": (315, 45),
124
+ "direito": (45, 135),
125
+ "inferior": (135, 225),
126
+ "esquerdo": (225, 315)
127
  }
128
 
 
 
129
  for setor, (ang_inicio, ang_fim) in setores.items():
130
+ # Criar máscara do setor
131
+ setor_mask = np.zeros_like(gray)
132
+ cv2.ellipse(setor_mask,
133
+ (ix, iy),
134
+ (ir, ir),
135
+ 0,
136
+ ang_inicio,
137
+ ang_fim,
138
+ 255,
139
  -1)
140
 
141
+ # Aplicar máscara do setor
142
+ setor_roi = cv2.bitwise_and(iris_ring, iris_ring, mask=setor_mask)
143
 
144
+ # Análises no setor
145
+ non_zero = setor_roi[setor_roi != 0]
146
+ if len(non_zero) > 0:
147
+ caracteristicas[setor] = {
148
+ "media": np.mean(non_zero),
149
+ "std": np.std(non_zero),
150
+ "min": np.min(non_zero),
151
+ "max": np.max(non_zero)
152
+ }
153
+
154
+ return caracteristicas
155
 
156
+ def analisar_padrao_collarette(imagem, pupila_info, iris_info):
157
  """
158
+ Analisa o padrão do collarette (anel ao redor da pupila)
159
  """
160
+ if pupila_info is None or iris_info is None:
161
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
+ px, py, pr = pupila_info
164
+ ix, iy, ir = iris_info
 
 
165
 
166
+ # Região do collarette (aprox. 1/3 da distância entre pupila e íris)
167
+ collarette_r = pr + int((ir - pr) * 0.33)
 
 
 
 
 
 
 
 
 
 
168
 
169
+ # Criar máscara anelar para o collarette
170
+ mask = np.zeros_like(cv2.cvtColor(imagem, cv2.COLOR_RGB2GRAY))
171
+ cv2.circle(mask, (px, py), collarette_r, 255, -1)
172
+ cv2.circle(mask, (px, py), pr, 0, -1)
 
 
 
 
173
 
174
+ # Aplicar máscara
175
+ collarette = cv2.bitwise_and(imagem, imagem, mask=mask)
 
 
176
 
177
+ # Análise do collarette
178
+ gray_collarette = cv2.cvtColor(collarette, cv2.COLOR_RGB2GRAY)
179
+ non_zero = gray_collarette[gray_collarette != 0]
180
 
181
+ if len(non_zero) > 0:
182
+ return {
183
+ "intensidade_media": np.mean(non_zero),
184
+ "variacao": np.std(non_zero),
185
+ "regularidade": cv2.Laplacian(gray_collarette, cv2.CV_64F).var()
186
+ }
187
 
188
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
 
190
  def criar_interface():
191
  """
192
+ Cria interface do Gradio com tema verde piscina
193
  """
 
194
  theme = gr.themes.Soft(
195
  primary_hue="teal",
196
  secondary_hue="green",
 
203
  button_primary_background_fill_dark="#264653",
204
  )
205
 
206
+ def processar_imagem(imagem):
207
+ # Detectar pupila e íris
208
+ output_img, pupila_info, iris_info = detectar_pupila_iris(imagem)
209
+
210
+ if pupila_info is None or iris_info is None:
211
+ return output_img, "Não foi possível detectar pupila ou íris corretamente."
212
+
213
+ # Extrair características
214
+ caracteristicas = extrair_caracteristicas_avancadas(imagem, pupila_info, iris_info)
215
+
216
+ # Analisar collarette
217
+ collarette_info = analisar_padrao_collarette(imagem, pupila_info, iris_info)
218
+
219
+ # Gerar relatório
220
+ relatorio = "ANÁLISE IRIDOLÓGICA DETALHADA\n\n"
221
+
222
+ # Informações da pupila
223
+ px, py, pr = pupila_info
224
+ relatorio += f"Pupila:\n"
225
+ relatorio += f"- Centro: ({px}, {py})\n"
226
+ relatorio += f"- Raio: {pr}px\n"
227
+
228
+ # Informações da íris
229
+ ix, iy, ir = iris_info
230
+ relatorio += f"\nÍris:\n"
231
+ relatorio += f"- Centro: ({ix}, {iy})\n"
232
+ relatorio += f"- Raio: {ir}px\n"
233
+
234
+ # Análise por setores
235
+ relatorio += "\nAnálise por Setores:\n"
236
+ for setor, dados in caracteristicas.items():
237
+ relatorio += f"\n{setor.title()}:\n"
238
+ relatorio += f"- Intensidade média: {dados['media']:.1f}\n"
239
+ relatorio += f"- Variação: {dados['std']:.1f}\n"
240
+
241
+ # Interpretar dados
242
+ if dados['std'] > 40:
243
+ relatorio += " * Alta variação - possível inflamação\n"
244
+ if dados['media'] < 100:
245
+ relatorio += " * Baixa intensidade - possível deficiência\n"
246
+
247
+ # Análise do collarette
248
+ if collarette_info:
249
+ relatorio += "\nAnálise do Collarette:\n"
250
+ if collarette_info['regularidade'] > 500:
251
+ relatorio += "- Irregularidade significativa\n"
252
+ if collarette_info['variacao'] > 30:
253
+ relatorio += "- Alta variação de textura\n"
254
+
255
+ return output_img, relatorio
256
+
257
  # Interface
258
+ with gr.Blocks(theme=theme, title="Análise Iridológica Avançada") as interface:
259
  gr.Markdown("""
260
  # Sistema Avançado de Análise Iridológica
261
+ ### Detecção precisa de pupila e íris com análise setorial
262
  """)
263
 
264
  with gr.Tabs():
 
268
  with gr.Column():
269
  input_image = gr.Image(
270
  label="Imagem da Íris",
271
+ type="numpy"
272
  )
273
  with gr.Column():
274
  output_image = gr.Image(
275
+ label="Análise Visual"
276
  )
277
 
278
  analysis_btn = gr.Button("Analisar Íris", variant="primary")
279
  output_text = gr.Textbox(
280
+ label="Relatório de Análise",
281
+ lines=15
282
  )
283
 
284
  analysis_btn.click(
 
287
  outputs=[output_image, output_text]
288
  )
289
 
290
+ # Aba de Informações
291
+ with gr.Tab("Guia de Captura"):
292
  gr.Markdown("""
293
+ ## Guia para Captura de Imagem
 
 
 
 
 
 
294
 
295
+ ### Requisitos da Imagem
296
+ 1. **Iluminação**
297
+ - Luz uniforme
298
+ - Sem reflexos na pupila
299
+ - Sem sombras fortes
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300
 
301
  2. **Posicionamento**
302
  - Olho bem aberto
303
+ - Íris centralizada
304
+ - Foco na íris
305
+
306
+ 3. **Qualidade**
307
+ - Alta resolução
308
+ - Imagem nítida
309
+ - Sem borramento
310
 
311
+ ### Dicas de Captura
312
+ - Use luz natural indireta
313
+ - Mantenha a câmera estável
314
+ - Capture múltiplas fotos
315
+ - Verifique o foco antes
316
  """)
317
 
318
  return interface