DHEIVER commited on
Commit
d600704
·
verified ·
1 Parent(s): dce5a99

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +157 -576
app.py CHANGED
@@ -1,586 +1,167 @@
1
  import gradio as gr
2
  import cv2
3
  import numpy as np
4
- from dataclasses import dataclass
5
- from typing import Dict, List, Tuple, Optional
6
- from datetime import datetime
7
-
8
- @dataclass
9
- class IrisZone:
10
- name: str
11
- ratio: Tuple[float, float] # (inner, outer)
12
- color: Tuple[int, int, int]
13
- conditions: Dict[str, List[str]]
14
- recommendations: Dict[str, List[str]]
15
-
16
- class IrisAnalyzer:
17
- def __init__(self):
18
- self.zones = [
19
- IrisZone(
20
- name="Zona Cerebral/Neural",
21
- ratio=(0.85, 1.0),
22
- color=(255, 0, 0),
23
- conditions={
24
- "baixa": [
25
- "Possível fadiga neural crônica",
26
- "Indicadores de estresse prolongado",
27
- "Sinais de insônia ou distúrbios do sono",
28
- "Possível déficit de vitamina B12"
29
- ],
30
- "media": ["Estado neural estável", "Função cognitiva normal"],
31
- "alta": ["Excelente saúde neural", "Ótima resposta cognitiva"]
32
- },
33
- recommendations={
34
- "baixa": [
35
- "Suplementação de vitamina B12",
36
- "Técnicas de meditação diária",
37
- "Melhorar qualidade do sono",
38
- "Reduzir exposição a telas"
39
- ],
40
- "media": ["Manter rotina de sono", "Exercícios mentais regulares"],
41
- "alta": ["Manter práticas atuais", "Exercícios de mindfulness"]
42
- }
43
- ),
44
- IrisZone(
45
- name="Zona Digestiva",
46
- ratio=(0.7, 0.85),
47
- color=(0, 255, 0),
48
- conditions={
49
- "baixa": [
50
- "Possível inflamação intestinal",
51
- "Sinais de má absorção",
52
- "Indicadores de disbiose",
53
- "Possível deficiência enzimática"
54
- ],
55
- "media": ["Digestão funcional", "Absorção adequada"],
56
- "alta": ["Excelente saúde digestiva", "Ótima absorção"]
57
- },
58
- recommendations={
59
- "baixa": [
60
- "Probióticos específicos",
61
- "Enzimas digestivas",
62
- "Dieta anti-inflamatória",
63
- "Eliminar alimentos processados"
64
- ],
65
- "media": ["Manter dieta balanceada", "Hidratação adequada"],
66
- "alta": ["Manter dieta atual", "Rotina alimentar saudável"]
67
- }
68
- ),
69
- IrisZone(
70
- name="Zona Respiratória",
71
- ratio=(0.55, 0.7),
72
- color=(0, 0, 255),
73
- conditions={
74
- "baixa": [
75
- "Possível comprometimento respiratório",
76
- "Sinais de baixa oxigenação",
77
- "Indicadores de congestão brônquica",
78
- "Possível sensibilidade respiratória"
79
- ],
80
- "media": ["Função respiratória adequada", "Oxigenação normal"],
81
- "alta": ["Excelente capacidade respiratória", "Ótima oxigenação"]
82
- },
83
- recommendations={
84
- "baixa": [
85
- "Exercícios respiratórios diários",
86
- "Avaliar qualidade do ar",
87
- "Considerar atividades aeróbicas",
88
- "Técnicas de respiração profunda"
89
- ],
90
- "media": ["Manter exercícios regulares", "Praticar respiração consciente"],
91
- "alta": ["Continuar práticas saudáveis", "Manter atividades aeróbicas"]
92
- }
93
- ),
94
- IrisZone(
95
- name="Zona Circulatória",
96
- ratio=(0.4, 0.55),
97
- color=(255, 255, 0),
98
- conditions={
99
- "baixa": [
100
- "Possível circulação periférica reduzida",
101
- "Indicadores de estagnação sanguínea",
102
- "Sinais de baixo fluxo sanguíneo",
103
- "Possível deficiência de ferro"
104
- ],
105
- "media": ["Circulação adequada", "Fluxo sanguíneo normal"],
106
- "alta": ["Excelente circulação", "Ótimo fluxo sanguíneo"]
107
- },
108
- recommendations={
109
- "baixa": [
110
- "Aumentar atividade física",
111
- "Considerar suplementação de ferro",
112
- "Massagens circulatórias",
113
- "Hidratação adequada"
114
- ],
115
- "media": ["Manter exercícios regulares", "Alimentação rica em ferro"],
116
- "alta": ["Manter rotina atual", "Continuar exercícios"]
117
- }
118
- ),
119
- IrisZone(
120
- name="Zona Linfática",
121
- ratio=(0.25, 0.4),
122
- color=(255, 0, 255),
123
- conditions={
124
- "baixa": [
125
- "Sistema linfático congestionado",
126
- "Possível retenção de líquidos",
127
- "Indicadores de toxicidade",
128
- "Baixa resposta imunológica"
129
- ],
130
- "media": ["Sistema linfático funcional", "Drenagem adequada"],
131
- "alta": ["Excelente drenagem linfática", "Ótima desintoxicação"]
132
- },
133
- recommendations={
134
- "baixa": [
135
- "Drenagem linfática regular",
136
- "Aumentar consumo de água",
137
- "Exercícios específicos",
138
- "Dieta desintoxicante"
139
- ],
140
- "media": ["Manter hidratação", "Exercícios leves regulares"],
141
- "alta": ["Manter hábitos atuais", "Continuar atividades físicas"]
142
- }
143
- ),
144
- IrisZone(
145
- name="Zona Endócrina",
146
- ratio=(0.15, 0.25),
147
- color=(0, 255, 255),
148
- conditions={
149
- "baixa": [
150
- "Possível desequilíbrio hormonal",
151
- "Sinais de estresse adrenal",
152
- "Indicadores de fadiga endócrina",
153
- "Possível disfunção tireoidiana"
154
- ],
155
- "media": ["Sistema endócrino estável", "Função hormonal adequada"],
156
- "alta": ["Excelente equilíbrio hormonal", "Ótima função endócrina"]
157
- },
158
- recommendations={
159
- "baixa": [
160
- "Gestão do estresse",
161
- "Suporte adrenal natural",
162
- "Regular ciclo sono-vigília",
163
- "Alimentação rica em iodo"
164
- ],
165
- "media": ["Manter rotina regular", "Cuidar do sono"],
166
- "alta": ["Manter equilíbrio atual", "Continuar boas práticas"]
167
- }
168
- ),
169
- IrisZone(
170
- name="Zona Pupilar",
171
- ratio=(0, 0.15),
172
- color=(128, 128, 128),
173
- conditions={
174
- "baixa": [
175
- "Sistema nervoso autônomo sobrecarregado",
176
- "Possível desequilíbrio simpático/parassimpático",
177
- "Indicadores de estresse crônico",
178
- "Sinais de fadiga autonômica"
179
- ],
180
- "media": ["SNA equilibrado", "Resposta autonômica normal"],
181
- "alta": ["Excelente regulação autonômica", "Ótimo equilíbrio do SNA"]
182
- },
183
- recommendations={
184
- "baixa": [
185
- "Técnicas de relaxamento",
186
- "Práticas de mindfulness",
187
- "Regular rotina diária",
188
- "Exercícios de respiração"
189
- ],
190
- "media": ["Manter práticas relaxantes", "Continuar boa rotina"],
191
- "alta": ["Manter equilíbrio atual", "Continuar práticas saudáveis"]
192
- }
193
- )
194
- ]
195
-
196
- def _assess_image_quality(self, image: np.ndarray) -> float:
197
- """Assess image quality with better error handling."""
198
- try:
199
- gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
200
- blur_score = cv2.Laplacian(gray, cv2.CV_64F).var()
201
- brightness = np.mean(gray)
202
- contrast = np.std(gray)
203
-
204
- quality_score = (
205
- np.clip(blur_score / 500, 0, 1) * 0.4 +
206
- np.clip(1 - abs(brightness - 128) / 128, 0, 1) * 0.3 +
207
- np.clip(contrast / 50, 0, 1) * 0.3
208
- ) * 100
209
-
210
- return float(quality_score)
211
- except Exception as e:
212
- print(f"Error in image quality assessment: {str(e)}")
213
- return 0.0
214
-
215
- def _analyze_texture(self, gray: np.ndarray, mask: np.ndarray) -> float:
216
- """Analyze texture with improved error handling and normalization."""
217
- try:
218
- if mask is None or np.sum(mask) == 0:
219
- return 0.0
220
-
221
- zone_pixels = cv2.bitwise_and(gray, gray, mask=mask)
222
- valid_pixels = zone_pixels[mask > 0]
223
-
224
- if len(valid_pixels) == 0:
225
- return 0.0
226
-
227
- mean = np.mean(valid_pixels)
228
- std = np.std(valid_pixels)
229
- entropy = np.sum(np.abs(np.diff(valid_pixels)))
230
-
231
- texture_score = (
232
- np.clip(mean / 255, 0, 1) * 0.3 +
233
- np.clip(std / 128, 0, 1) * 0.3 +
234
- np.clip(entropy / 1000, 0, 1) * 0.4
235
- ) * 100
236
-
237
- return float(texture_score)
238
- except Exception as e:
239
- print(f"Error in texture analysis: {str(e)}")
240
- return 0.0
241
-
242
- def _analyze_contrast(self, l_channel: np.ndarray, mask: np.ndarray) -> float:
243
- """Analyze contrast with improved error handling."""
244
- try:
245
- if mask is None or np.sum(mask) == 0:
246
- return 0.0
247
-
248
- zone_pixels = l_channel[mask > 0]
249
- if len(zone_pixels) == 0:
250
- return 0.0
251
-
252
- p5 = np.percentile(zone_pixels, 5)
253
- p95 = np.percentile(zone_pixels, 95)
254
-
255
- contrast_score = np.clip((p95 - p5) / 255, 0, 1) * 100
256
- return float(contrast_score)
257
- except Exception as e:
258
- print(f"Error in contrast analysis: {str(e)}")
259
- return 0.0
260
-
261
- def _detect_patterns(self, gray: np.ndarray, mask: np.ndarray) -> float:
262
- """Detect patterns with improved error handling."""
263
- try:
264
- if mask is None or np.sum(mask) == 0:
265
- return 0.0
266
-
267
- sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
268
- sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)
269
- gradient = np.sqrt(sobelx**2 + sobely**2)
270
-
271
- zone_gradient = gradient[mask > 0]
272
- if len(zone_gradient) == 0 or np.max(gradient) == 0:
273
- return 0.0
274
-
275
- pattern_score = np.clip((np.mean(zone_gradient) / np.max(gradient)), 0, 1) * 100
276
- return float(pattern_score)
277
- except Exception as e:
278
- print(f"Error in pattern detection: {str(e)}")
279
- return 0.0
280
-
281
- def _customize_conditions(self, base_conditions: List[str], metrics: Dict) -> List[str]:
282
- """Customize conditions based on metrics."""
283
- customized = []
284
- for condition in base_conditions:
285
- if metrics["intensity"] < 50:
286
- condition += " (intensidade muito baixa)"
287
- elif metrics["contrast"] < 30:
288
- condition += " (baixo contraste)"
289
-
290
- if metrics["patterns"] > 70:
291
- condition += " (padrões significativos detectados)"
292
-
293
- customized.append(condition)
294
- return customized
295
-
296
- def _customize_recommendations(self, base_recommendations: List[str], metrics: Dict) -> List[str]:
297
- """Customize recommendations based on metrics."""
298
- customized = []
299
- for rec in base_recommendations:
300
- if metrics["texture"] < 40:
301
- rec += " (prioridade alta)"
302
- elif metrics["saturation"] < 50:
303
- rec += " (atenção especial necessária)"
304
-
305
- customized.append(rec)
306
- return customized
307
-
308
- def _calculate_confidence(self, metrics: Dict) -> str:
309
- """Calculate analysis confidence level."""
310
- confidence_score = (
311
- metrics["intensity"] * 0.25 +
312
- metrics["contrast"] * 0.25 +
313
- metrics["texture"] * 0.25 +
314
- metrics["patterns"] * 0.25
315
- )
316
-
317
- if confidence_score > 75:
318
- return "alta"
319
- elif confidence_score > 50:
320
- return "média"
321
- else:
322
- return "baixa"
323
-
324
- def analyze_iris(self, image: np.ndarray) -> Tuple[np.ndarray, Dict]:
325
- """Main analysis function with improved error handling and image processing."""
326
- try:
327
- # Convert BGR to RGB if needed
328
- if len(image.shape) == 2:
329
- image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
330
- elif image.shape[2] == 4:
331
- image = cv2.cvtColor(image, cv2.COLOR_BGRA2BGR)
332
-
333
- # Create copies for different color spaces
334
- gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
335
- hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
336
- lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)
337
-
338
- # Improve circle detection
339
- circles = cv2.HoughCircles(
340
- gray,
341
- cv2.HOUGH_GRADIENT,
342
- dp=1,
343
- minDist=max(gray.shape[0], gray.shape[1]), # Only detect one circle
344
- param1=50,
345
- param2=30,
346
- minRadius=min(gray.shape) // 6,
347
- maxRadius=min(gray.shape) // 2
348
- )
349
-
350
- if circles is not None:
351
- circles = np.uint16(np.around(circles))
352
- circle = circles[0][0]
353
- center = (int(circle[0]), int(circle[1]))
354
- radius = int(circle[2])
355
- else:
356
- # Fallback to image center if no circle is detected
357
- center = (image.shape[1] // 2, image.shape[0] // 2)
358
- radius = min(image.shape[:2]) // 4
359
-
360
- results = {
361
- "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
362
- "analysis": {},
363
- "metrics": {
364
- "iris_radius": radius,
365
- "image_quality": self._assess_image_quality(image)
366
- }
367
- }
368
-
369
- # Analysis for each zone
370
- for zone in self.zones:
371
- inner_r = int(radius * zone.ratio[0])
372
- outer_r = int(radius * zone.ratio[1])
373
-
374
- # Create zone mask
375
- mask = np.zeros(gray.shape, dtype=np.uint8)
376
- cv2.circle(mask, center, outer_r, 255, -1)
377
- cv2.circle(mask, center, inner_r, 0, -1)
378
-
379
- # Calculate metrics
380
- zone_metrics = {
381
- "intensity": float(cv2.mean(gray, mask=mask)[0]),
382
- "saturation": float(cv2.mean(hsv[..., 1], mask=mask)[0]),
383
- "texture": self._analyze_texture(gray, mask),
384
- "contrast": self._analyze_contrast(lab[..., 0], mask),
385
- "patterns": self._detect_patterns(gray, mask)
386
- }
387
-
388
- # Calculate health score
389
- health_score = (
390
- zone_metrics["intensity"] * 0.3 +
391
- zone_metrics["saturation"] * 0.2 +
392
- zone_metrics["texture"] * 0.2 +
393
- zone_metrics["contrast"] * 0.15 +
394
- zone_metrics["patterns"] * 0.15
395
- )
396
-
397
- # Determine health level
398
- level = "baixa" if health_score < 40 else ("media" if health_score < 75 else "alta")
399
-
400
- # Store results
401
- results["analysis"][zone.name] = {
402
- "conditions": self._customize_conditions(zone.conditions[level], zone_metrics),
403
- "recommendations": self._customize_recommendations(zone.recommendations[level], zone_metrics),
404
- "metrics": {k: float(v) for k, v in zone_metrics.items()},
405
- "health_score": float(health_score),
406
- "status": level,
407
- "confianca_analise": self._calculate_confidence(zone_metrics)
408
- }
409
-
410
- # Draw zone visualization
411
- cv2.circle(image, center, outer_r, zone.color, 2)
412
- cv2.putText(
413
- image,
414
- zone.name,
415
- (center[0] - outer_r, center[1] + outer_r),
416
- cv2.FONT_HERSHEY_SIMPLEX,
417
- 0.5,
418
- zone.color,
419
- 1,
420
- cv2.LINE_AA
421
- )
422
-
423
- return image, results
424
-
425
- except Exception as e:
426
- print(f"Error in iris analysis: {str(e)}")
427
- return image, {"error": str(e)}
428
-
429
- def process_image(img: Optional[np.ndarray]) -> Tuple[Optional[np.ndarray], str, str, str, str]:
430
- """Process image with improved error handling and input validation."""
431
- if img is None:
432
- return None, "⚠️ Por favor, carregue uma imagem.", "", "", ""
433
 
434
- try:
435
- analyzer = IrisAnalyzer()
436
- processed_img, results = analyzer.analyze_iris(img)
437
-
438
- if "error" in results:
439
- return None, f"⚠️ Erro na análise: {results['error']}", "", "", ""
440
-
441
- # Generate reports
442
- general_report = "# 📊 Visão Geral da Análise\n\n"
443
- status_counts = {"baixa": 0, "media": 0, "alta": 0}
444
-
445
- for analysis in results["analysis"].values():
446
- status_counts[analysis["status"]] += 1
447
-
448
- health_score = (
449
- (status_counts["alta"] * 100 + status_counts["media"] * 50) /
450
- max(1, len(results["analysis"]))
451
- )
452
-
453
- general_report += (
454
- f"**Índice de Saúde Geral:** {health_score:.1f}%\n\n"
455
- f"**Data da Análise:** {results['timestamp']}\n\n"
456
- f"**Qualidade da Imagem:** {results['metrics']['image_quality']:.1f}%\n\n"
457
- )
458
-
459
- # Detailed reports
460
- detailed_conditions = "# 🔍 Análise Detalhada por Zona\n\n"
461
- recommendations = "# 💡 Recomendações Personalizadas\n\n"
462
- health_alerts = "# ⚠️ Alertas e Atenção Especial\n\n"
463
-
464
- for zone_name, analysis in results["analysis"].items():
465
- # Add detailed conditions
466
- detailed_conditions += f"## {zone_name}\n\n"
467
- detailed_conditions += "### Condições Identificadas:\n"
468
- for condition in analysis["conditions"]:
469
- detailed_conditions += f"- {condition}\n"
470
- detailed_conditions += (
471
- f"\n**Status:** {analysis['status'].title()}\n"
472
- f"**Confiança da Análise:** {analysis['confianca_analise']}\n"
473
- "**Métricas Detalhadas:**\n"
474
- )
475
- for metric, value in analysis["metrics"].items():
476
- detailed_conditions += f"- {metric.replace('_', ' ').title()}: {value:.1f}\n"
477
- detailed_conditions += "\n"
478
-
479
- # Add recommendations
480
- recommendations += f"## {zone_name}\n\n"
481
- for rec in analysis["recommendations"]:
482
- recommendations += f"- {rec}\n"
483
- recommendations += "\n"
484
-
485
- # Add health alerts
486
- if analysis["status"] == "baixa" or analysis["metrics"]["health_score"] < 50:
487
- health_alerts += f"## {zone_name}\n"
488
- health_alerts += "### Pontos de Atenção:\n"
489
- for condition in analysis["conditions"]:
490
- health_alerts += f"- ⚠️ {condition}\n"
491
- health_alerts += "\n### Ações Recomendadas:\n"
492
- for rec in analysis["recommendations"]:
493
- health_alerts += f"- ✅ {rec}\n"
494
- health_alerts += "\n"
495
-
496
- return processed_img, general_report, detailed_conditions, recommendations, health_alerts
497
-
498
- except Exception as e:
499
- error_message = f"⚠️ Erro no processamento: {str(e)}"
500
- return None, error_message, "", "", ""
501
-
502
- # Gradio Interface
503
- with gr.Blocks(theme=gr.themes.Soft()) as iface:
504
- gr.Markdown("""
505
- # 🔍 Analisador Avançado de Íris
506
- ### Sistema Educacional de Análise Iridológica v2.0
507
 
508
- ⚠️ Este é um sistema para fins educacionais. Não utilize para diagnósticos médicos.
509
- """)
 
 
 
 
 
 
 
 
 
510
 
511
- with gr.Tabs() as tabs:
512
- with gr.Tab("📸 Análise de Imagem"):
513
- with gr.Row():
514
- with gr.Column(scale=1):
515
- input_image = gr.Image(
516
- label="Upload da Imagem da Íris",
517
- type="numpy",
518
- sources=["upload", "webcam", "clipboard"],
519
- height=400
520
- )
521
- analyze_btn = gr.Button("🔍 Analisar Íris", variant="primary", size="lg")
522
-
523
- with gr.Column(scale=1):
524
- output_image = gr.Image(label="Visualização da Análise", height=400)
525
-
526
- with gr.Tab("📊 Resultados"):
527
- with gr.Tabs() as result_tabs:
528
- with gr.Tab("📈 Visão Geral"):
529
- general_output = gr.Markdown()
530
-
531
- with gr.Tab("🔍 Condições Detalhadas"):
532
- conditions_output = gr.Markdown()
533
-
534
- with gr.Tab("💡 Recomendações"):
535
- recommendations_output = gr.Markdown()
536
-
537
- with gr.Tab("⚠️ Alertas"):
538
- alerts_output = gr.Markdown()
539
-
540
- with gr.Tab("ℹ️ Informações"):
541
- gr.Markdown("""
542
- ## 📚 Sobre a Análise Iridológica
543
-
544
- ### 🎯 Zonas Analisadas:
545
- 1. **Zona Cerebral/Neural** - Sistema nervoso central e periférico
546
- 2. **Zona Digestiva** - Sistema digestório completo
547
- 3. **Zona Respiratória** - Sistema respiratório
548
- 4. **Zona Circulatória** - Sistema cardiovascular
549
- 5. **Zona Linfática** - Sistema imunológico
550
- 6. **Zona Endócrina** - Sistema hormonal
551
- 7. **Zona Pupilar** - Sistema nervoso autônomo
552
-
553
- ### 📋 Como Usar:
554
- 1. Faça upload de uma imagem clara da íris
555
- 2. Clique em "Analisar Íris"
556
- 3. Verifique os resultados nas diferentes abas
557
- 4. Consulte os alertas e recomendações
558
-
559
- ### 🔍 Interpretação dos Resultados:
560
- - **Visão Geral**: Índice geral de saúde e qualidade da análise
561
- - **Condições**: Análise detalhada por zona
562
- - **Recomendações**: Sugestões personalizadas
563
- - **Alertas**: Pontos que requerem atenção especial
564
-
565
- ### ⚠️ Observações Importantes:
566
- - Sistema para fins educacionais
567
- - Não substitui avaliação médica
568
- - Consulte profissionais de saúde
569
- - Mantenha check-ups regulares
570
- """)
571
 
572
- # Event handlers
573
- analyze_btn.click(
574
- fn=process_image,
575
- inputs=input_image,
576
- outputs=[
577
- output_image,
578
- general_output,
579
- conditions_output,
580
- recommendations_output,
581
- alerts_output
582
- ]
 
 
 
 
 
 
 
 
 
 
 
 
583
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
584
 
585
  if __name__ == "__main__":
586
- iface.launch()
 
1
  import gradio as gr
2
  import cv2
3
  import numpy as np
4
+ from PIL import Image
5
+ import io
6
+
7
+ def analisar_iris(imagem):
8
+ """
9
+ Função para analisar a íris através de processamento de imagem
10
+ """
11
+ # Converter para array numpy
12
+ img_array = np.array(imagem)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
+ # Converter para escala de cinza
15
+ gray = cv2.cvtColor(img_array, cv2.COLOR_RGB2GRAY)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ # Detectar círculos (íris) usando transformada de Hough
18
+ circles = cv2.HoughCircles(
19
+ gray,
20
+ cv2.HOUGH_GRADIENT,
21
+ dp=1,
22
+ minDist=50,
23
+ param1=50,
24
+ param2=30,
25
+ minRadius=20,
26
+ maxRadius=100
27
+ )
28
 
29
+ # Criar cópia da imagem para desenhar
30
+ output = img_array.copy()
31
+
32
+ resultados = []
33
+
34
+ if circles is not None:
35
+ circles = np.uint16(np.around(circles))
36
+ for i in circles[0, :]:
37
+ # Desenhar círculo externo
38
+ cv2.circle(output, (i[0], i[1]), i[2], (0, 255, 0), 2)
39
+ # Desenhar centro
40
+ cv2.circle(output, (i[0], i[1]), 2, (0, 0, 255), 3)
41
+
42
+ # Análise de características
43
+ roi = gray[i[1]-i[2]:i[1]+i[2], i[0]-i[2]:i[0]+i[2]]
44
+ if roi.size > 0:
45
+ media = np.mean(roi)
46
+ std = np.std(roi)
47
+
48
+ resultados.append(f"Análise da Íris:")
49
+ resultados.append(f"- Densidade média: {media:.2f}")
50
+ resultados.append(f"- Variação de textura: {std:.2f}")
51
+
52
+ # Análise de setores
53
+ altura, largura = roi.shape
54
+ setor_superior = np.mean(roi[:altura//3, :])
55
+ setor_medio = np.mean(roi[altura//3:2*altura//3, :])
56
+ setor_inferior = np.mean(roi[2*altura//3:, :])
57
+
58
+ resultados.append("\nAnálise por Setores:")
59
+ resultados.append(f"- Setor Superior: {setor_superior:.2f}")
60
+ resultados.append(f"- Setor Médio: {setor_medio:.2f}")
61
+ resultados.append(f"- Setor Inferior: {setor_inferior:.2f}")
62
+
63
+ return output, "\n".join(resultados)
64
+
65
+ def gerar_relatorio(imagem, nome_paciente, idade, data_analise):
66
+ """
67
+ Função para gerar relatório completo da análise
68
+ """
69
+ img_array = np.array(imagem)
70
+ resultado_analise, metricas = analisar_iris(imagem)
71
+
72
+ relatorio = f"""
73
+ RELATÓRIO DE ANÁLISE IRIDOLÓGICA
74
+
75
+ Data: {data_analise}
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
+ DADOS DO PACIENTE
78
+ Nome: {nome_paciente}
79
+ Idade: {idade}
80
+
81
+ ANÁLISE TÉCNICA
82
+ {metricas}
83
+
84
+ OBSERVAÇÕES GERAIS
85
+ - Análise realizada com processamento computadorizado de imagem
86
+ - Recomenda-se acompanhamento profissional para interpretação detalhada
87
+ """
88
+
89
+ return relatorio
90
+
91
+ def main():
92
+ # Configuração do tema
93
+ theme = gr.themes.Soft(
94
+ primary_hue="blue",
95
+ secondary_hue="gray",
96
+ ).set(
97
+ body_background_fill="*neutral_50",
98
+ block_background_fill="*neutral_100",
99
+ button_primary_background_fill="*primary_500",
100
  )
101
+
102
+ # Criação da interface
103
+ with gr.Blocks(theme=theme, title="Análise Iridológica") as iface:
104
+ gr.Markdown("# Sistema de Análise Iridológica")
105
+
106
+ with gr.Tabs():
107
+ # Aba de Análise Básica
108
+ with gr.Tab("Análise Básica"):
109
+ with gr.Row():
110
+ with gr.Column():
111
+ input_image = gr.Image(label="Carregar Imagem da Íris", type="pil")
112
+ with gr.Column():
113
+ output_image = gr.Image(label="Íris Analisada")
114
+ output_text = gr.Textbox(label="Resultados da Análise", lines=10)
115
+
116
+ analyze_btn = gr.Button("Realizar Análise", variant="primary")
117
+ analyze_btn.click(
118
+ fn=analisar_iris,
119
+ inputs=[input_image],
120
+ outputs=[output_image, output_text]
121
+ )
122
+
123
+ # Aba de Relatório Completo
124
+ with gr.Tab("Relatório Completo"):
125
+ with gr.Row():
126
+ with gr.Column():
127
+ nome_input = gr.Textbox(label="Nome do Paciente")
128
+ idade_input = gr.Number(label="Idade", minimum=0, maximum=120)
129
+ data_input = gr.Textbox(label="Data da Análise")
130
+ report_image = gr.Image(label="Carregar Imagem da Íris", type="pil")
131
+
132
+ with gr.Column():
133
+ report_output = gr.Textbox(label="Relatório Completo", lines=15)
134
+
135
+ report_btn = gr.Button("Gerar Relatório", variant="primary")
136
+ report_btn.click(
137
+ fn=gerar_relatorio,
138
+ inputs=[report_image, nome_input, idade_input, data_input],
139
+ outputs=[report_output]
140
+ )
141
+
142
+ # Aba de Informações
143
+ with gr.Tab("Informações"):
144
+ gr.Markdown("""
145
+ ## Sobre a Análise Iridológica
146
+
147
+ A iridologia é uma técnica de análise que estuda os sinais presentes na íris dos olhos
148
+ para avaliar características e condições do organismo. Este sistema realiza uma análise
149
+ computadorizada preliminar, que deve ser interpretada por um profissional qualificado.
150
+
151
+ ### Recursos do Sistema:
152
+ 1. Análise básica da íris com detecção automática
153
+ 2. Medições de densidade e textura
154
+ 3. Análise setorial da íris
155
+ 4. Geração de relatórios personalizados
156
+
157
+ ### Recomendações:
158
+ - Utilize fotos em boa resolução
159
+ - Certifique-se de que a íris está bem iluminada
160
+ - A imagem deve estar focada e nítida
161
+ """)
162
+
163
+ # Iniciar a interface
164
+ iface.launch(share=True)
165
 
166
  if __name__ == "__main__":
167
+ main()