Spaces:
Sleeping
Sleeping
import gradio as gr | |
import cv2 | |
import numpy as np | |
from PIL import Image | |
from dataclasses import dataclass | |
from typing import Tuple, Dict, List | |
import torch | |
import torch.nn.functional as F | |
import torchvision.transforms as transforms | |
class IrisZone: | |
name: str | |
inner_ratio: float | |
outer_ratio: float | |
color: Tuple[int, int, int] | |
angle_start: float = 0 | |
angle_end: float = 360 | |
class IrisAnalyzer: | |
def __init__(self): | |
# Define zonas com cores distintas e ângulos específicos | |
self.zones = [ | |
IrisZone("Zona Cerebral/Neural", 0.85, 1.0, (255, 0, 0)), | |
IrisZone("Zona Digestiva", 0.7, 0.85, (0, 255, 0)), | |
IrisZone("Zona Respiratória", 0.55, 0.7, (0, 0, 255)), | |
IrisZone("Zona Circulatória", 0.4, 0.55, (255, 255, 0)), | |
IrisZone("Zona Linfática", 0.25, 0.4, (255, 0, 255)), | |
IrisZone("Zona Endócrina", 0.15, 0.25, (0, 255, 255)), | |
IrisZone("Zona Pupilar", 0, 0.15, (128, 128, 128)) | |
] | |
def preprocess_image(self, img: np.ndarray) -> np.ndarray: | |
"""Pré-processa a imagem para melhorar a detecção""" | |
# Converter para escala de cinza | |
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) | |
# Aplicar equalização de histograma adaptativo | |
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) | |
enhanced = clahe.apply(gray) | |
# Redução de ruído | |
denoised = cv2.fastNlMeansDenoising(enhanced) | |
return denoised | |
def detect_pupil(self, img: np.ndarray) -> Tuple[int, int, int]: | |
"""Detecta a pupila usando técnicas avançadas""" | |
preprocessed = self.preprocess_image(img) | |
# Threshold adaptativo | |
_, thresh = cv2.threshold(preprocessed, 30, 255, | |
cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) | |
# Operações morfológicas | |
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5)) | |
morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) | |
# Encontrar contornos | |
contours, _ = cv2.findContours(morph, cv2.RETR_EXTERNAL, | |
cv2.CHAIN_APPROX_SIMPLE) | |
if not contours: | |
return None | |
# Encontrar o contorno mais circular | |
max_circularity = 0 | |
best_contour = None | |
for contour in contours: | |
area = cv2.contourArea(contour) | |
perimeter = cv2.arcLength(contour, True) | |
if perimeter == 0: | |
continue | |
circularity = 4 * np.pi * area / (perimeter * perimeter) | |
if circularity > max_circularity: | |
max_circularity = circularity | |
best_contour = contour | |
if best_contour is None: | |
return None | |
# Ajustar círculo | |
(x, y), radius = cv2.minEnclosingCircle(best_contour) | |
return (int(x), int(y), int(radius)) | |
def analyze_zone(self, img: np.ndarray, mask: np.ndarray) -> Dict: | |
"""Analisa características da zona usando a máscara""" | |
# Extrair características da região | |
mean_color = cv2.mean(img, mask=mask) | |
# Calcular textura usando GLCM | |
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) | |
zone_pixels = cv2.bitwise_and(gray, gray, mask=mask) | |
# Análise de textura básica | |
if np.sum(mask) > 0: | |
std_dev = np.std(zone_pixels[mask > 0]) | |
mean_intensity = np.mean(zone_pixels[mask > 0]) | |
else: | |
std_dev = 0 | |
mean_intensity = 0 | |
return { | |
'mean_intensity': mean_intensity, | |
'std_dev': std_dev, | |
'color_variation': mean_color[:3] | |
} | |
def interpret_zone(self, analysis: Dict) -> str: | |
"""Interpreta os resultados da análise""" | |
intensity = analysis['mean_intensity'] | |
variation = analysis['std_dev'] | |
if intensity < 85: | |
base_condition = "Possível área de atenção" | |
elif intensity < 170: | |
base_condition = "Área moderada" | |
else: | |
base_condition = "Área normal" | |
detail = f"(Intensidade: {intensity:.1f}, Variação: {variation:.1f})" | |
return f"{base_condition} {detail}" | |
def analyze_iris(self, img: np.ndarray) -> Tuple[np.ndarray, Dict]: | |
"""Análise principal da íris""" | |
# Criar cópia para desenho | |
output_img = img.copy() | |
results = {} | |
# Detectar pupila | |
pupil = self.detect_pupil(img) | |
if pupil is None: | |
return img, {"Erro": "Não foi possível detectar a pupila"} | |
x, y, pupil_radius = pupil | |
# Estimar raio da íris (aproximadamente 4x o raio da pupila) | |
iris_radius = pupil_radius * 4 | |
# Desenhar círculo da pupila | |
cv2.circle(output_img, (x, y), pupil_radius, (0, 0, 0), 2) | |
# Analisar cada zona | |
for zone in self.zones: | |
inner_r = int(iris_radius * zone.inner_ratio) | |
outer_r = int(iris_radius * zone.outer_ratio) | |
# Criar máscara para a zona | |
mask = np.zeros(img.shape[:2], dtype=np.uint8) | |
cv2.circle(mask, (x, y), outer_r, 255, -1) | |
cv2.circle(mask, (x, y), inner_r, 0, -1) | |
# Desenhar círculos da zona | |
cv2.circle(output_img, (x, y), outer_r, zone.color, 2) | |
# Analisar zona | |
analysis = self.analyze_zone(img, mask) | |
interpretation = self.interpret_zone(analysis) | |
results[zone.name] = interpretation | |
# Adicionar texto | |
text_x = x - iris_radius | |
text_y = y + outer_r | |
cv2.putText(output_img, zone.name, (text_x, text_y), | |
cv2.FONT_HERSHEY_SIMPLEX, 0.5, zone.color, 1) | |
return output_img, results | |
def process_image(img): | |
analyzer = IrisAnalyzer() | |
return analyzer.analyze_iris(np.array(img)) | |
# Interface Gradio | |
iface = gr.Interface( | |
fn=process_image, | |
inputs=gr.Image(), | |
outputs=[ | |
gr.Image(label="Análise Visual"), | |
gr.JSON(label="Resultados da Análise por Zona") | |
], | |
title="Analisador Avançado de Íris (Baseado na Teoria de Jensen)", | |
description="""AVISO: Esta é uma demonstração educacional baseada na teoria de iridologia. | |
Esta não é uma ferramenta diagnóstica validada cientificamente e não deve ser usada para | |
decisões médicas. Consulte sempre um profissional de saúde qualificado para diagnósticos.""", | |
examples=[], | |
theme="default" | |
) | |
if __name__ == "__main__": | |
iface.launch() |