Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -13,210 +13,178 @@ class IridologyAnalyzer:
|
|
13 |
def __init__(self):
|
14 |
print("Inicializando analisador avançado...")
|
15 |
|
16 |
-
#
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
"recomendações": ["Monitoramento periódico", "Considerar práticas de redução de estresse"]
|
28 |
-
},
|
29 |
-
"simples": {
|
30 |
-
"observações": ["Padrão dentro do esperado"],
|
31 |
-
"nível": "Normal",
|
32 |
-
"recomendações": ["Manter hábitos saudáveis"]
|
33 |
-
}
|
34 |
-
},
|
35 |
-
"Coloração": {
|
36 |
-
"muito rica": {
|
37 |
-
"observações": ["Possível atividade metabólica intensificada", "Potencial desequilíbrio hormonal"],
|
38 |
-
"nível": "Requer atenção",
|
39 |
-
"recomendações": ["Verificar níveis hormonais", "Avaliar função da tireoide"]
|
40 |
-
},
|
41 |
-
"moderadamente": {
|
42 |
-
"observações": ["Metabolismo em adaptação"],
|
43 |
-
"nível": "Observação",
|
44 |
-
"recomendações": ["Monitorar níveis energéticos", "Avaliar padrões de sono"]
|
45 |
-
},
|
46 |
-
"simples": {
|
47 |
-
"observações": ["Metabolismo equilibrado"],
|
48 |
-
"nível": "Normal",
|
49 |
-
"recomendações": ["Manter dieta balanceada"]
|
50 |
-
}
|
51 |
-
},
|
52 |
-
"Marcas ou manchas": {
|
53 |
-
"complexo": {
|
54 |
-
"observações": ["Possível acúmulo de toxinas", "Potencial sobrecarga hepática"],
|
55 |
-
"nível": "Requer atenção",
|
56 |
-
"recomendações": ["Avaliação da função hepática", "Considerar detoxificação supervisionada"]
|
57 |
-
},
|
58 |
-
"moderado": {
|
59 |
-
"observações": ["Sistema de eliminação em adaptação"],
|
60 |
-
"nível": "Observação",
|
61 |
-
"recomendações": ["Aumentar ingestão de água", "Melhorar alimentação"]
|
62 |
-
},
|
63 |
-
"simples": {
|
64 |
-
"observações": ["Sistema de eliminação equilibrado"],
|
65 |
-
"nível": "Normal",
|
66 |
-
"recomendações": ["Manter hidratação adequada"]
|
67 |
-
}
|
68 |
-
},
|
69 |
-
"Anéis ou círculos": {
|
70 |
-
"não concêntricos": {
|
71 |
-
"observações": ["Possível desequilíbrio circulatório", "Tensão sistêmica"],
|
72 |
-
"nível": "Requer atenção",
|
73 |
-
"recomendações": ["Verificar pressão arterial", "Avaliar circulação"]
|
74 |
-
},
|
75 |
-
"moderadamente": {
|
76 |
-
"observações": ["Sistema circulatório em adaptação"],
|
77 |
-
"nível": "Observação",
|
78 |
-
"recomendações": ["Exercícios leves", "Monitorar pressão"]
|
79 |
-
}
|
80 |
-
},
|
81 |
-
"Clareza geral": {
|
82 |
-
"baixa": {
|
83 |
-
"observações": ["Possível congestão sistêmica", "Fadiga celular"],
|
84 |
-
"nível": "Requer atenção",
|
85 |
-
"recomendações": ["Avaliação nutricional", "Verificar níveis de vitaminas"]
|
86 |
-
},
|
87 |
-
"moderada": {
|
88 |
-
"observações": ["Sistema em processo de limpeza"],
|
89 |
-
"nível": "Observação",
|
90 |
-
"recomendações": ["Melhorar qualidade do sono", "Aumentar consumo de vegetais"]
|
91 |
-
},
|
92 |
-
"excepcional": {
|
93 |
-
"observações": ["Boa vitalidade celular"],
|
94 |
-
"nível": "Normal",
|
95 |
-
"recomendações": ["Manter estilo de vida saudável"]
|
96 |
-
}
|
97 |
-
}
|
98 |
-
}
|
99 |
-
|
100 |
-
self.iris_features = {
|
101 |
-
"Textura da íris": self._analyze_texture,
|
102 |
-
"Coloração": self._analyze_color,
|
103 |
-
"Marcas ou manchas": self._analyze_spots,
|
104 |
-
"Anéis ou círculos": self._analyze_rings,
|
105 |
-
"Condição da pupila": self._analyze_pupil,
|
106 |
-
"Linhas radiais": self._analyze_lines,
|
107 |
-
"Pigmentação": self._analyze_pigmentation,
|
108 |
-
"Clareza geral": self._analyze_clarity,
|
109 |
-
"Estrutura do tecido": self._analyze_tissue,
|
110 |
-
"Marcas brancas": self._analyze_white_marks,
|
111 |
-
"Fibras da íris": self._analyze_fibers,
|
112 |
-
"Borda da íris": self._analyze_border
|
113 |
-
}
|
114 |
-
|
115 |
-
self.texture_params = {
|
116 |
-
'distances': [1, 2, 3],
|
117 |
-
'angles': [0, np.pi/4, np.pi/2, 3*np.pi/4]
|
118 |
-
}
|
119 |
-
|
120 |
-
print("Analisador avançado inicializado com sucesso!")
|
121 |
-
|
122 |
-
# [Previous analysis methods remain unchanged...]
|
123 |
-
|
124 |
-
def comprehensive_analysis(self, image):
|
125 |
-
"""Realiza uma análise completa e detalhada da íris com correlações de saúde."""
|
126 |
-
try:
|
127 |
-
enhanced, original = self._preprocess_image(image)
|
128 |
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
results.append({
|
138 |
-
"feature": feature,
|
139 |
-
"analysis": description,
|
140 |
-
"value": float(value) if value is not None else 0
|
141 |
-
})
|
142 |
-
|
143 |
-
# Adicionar correlações de saúde se disponíveis
|
144 |
-
if feature in self.health_correlations:
|
145 |
-
for pattern_key, correlation in self.health_correlations[feature].items():
|
146 |
-
if pattern_key in description.lower():
|
147 |
-
health_insights.append({
|
148 |
-
"feature": feature,
|
149 |
-
"observações": correlation["observações"],
|
150 |
-
"nível": correlation["nível"],
|
151 |
-
"recomendações": correlation.get("recomendações", [])
|
152 |
-
})
|
153 |
-
|
154 |
-
# Calcular score de saúde
|
155 |
-
if correlation["nível"] == "Normal":
|
156 |
-
overall_health_score += 100
|
157 |
-
elif correlation["nível"] == "Observação":
|
158 |
-
overall_health_score += 70
|
159 |
-
elif correlation["nível"] == "Requer atenção":
|
160 |
-
overall_health_score += 40
|
161 |
-
total_features += 1
|
162 |
-
|
163 |
-
except Exception as e:
|
164 |
-
print(f"Erro ao analisar '{feature}': {str(e)}")
|
165 |
-
continue
|
166 |
|
167 |
-
|
168 |
-
if total_features > 0:
|
169 |
-
overall_health_score = overall_health_score / total_features
|
170 |
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
|
|
|
|
|
|
175 |
|
176 |
-
|
177 |
-
"""
|
|
|
|
|
|
|
178 |
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
|
183 |
-
|
184 |
-
|
185 |
-
for
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
formatted_results += "-" * 30 + "\n"
|
191 |
-
|
192 |
-
# Adicionar insights de saúde
|
193 |
-
if health_insights:
|
194 |
-
formatted_results += "\nCORRELAÇÕES DE SAÚDE OBSERVADAS:\n"
|
195 |
-
for insight in health_insights:
|
196 |
-
formatted_results += f"\nCaracterística: {insight['feature']}\n"
|
197 |
-
formatted_results += f"Nível: {insight['nível']}\n"
|
198 |
-
formatted_results += "Observações:\n"
|
199 |
-
for obs in insight['observações']:
|
200 |
-
formatted_results += f"- {obs}\n"
|
201 |
-
if insight.get('recomendações'):
|
202 |
-
formatted_results += "Recomendações:\n"
|
203 |
-
for rec in insight['recomendações']:
|
204 |
-
formatted_results += f"- {rec}\n"
|
205 |
-
formatted_results += "-" * 30 + "\n"
|
206 |
-
|
207 |
-
# Adicionar disclaimer final
|
208 |
-
formatted_results += """
|
209 |
-
LEMBRETE IMPORTANTE:
|
210 |
-
1. Esta análise é baseada em padrões visuais e NÃO é um diagnóstico médico
|
211 |
-
2. Os resultados devem ser interpretados por profissionais qualificados
|
212 |
-
3. Sempre busque avaliação médica profissional para diagnóstico e tratamento
|
213 |
-
4. Esta ferramenta é um complemento e NÃO substitui exames clínicos convencionais
|
214 |
-
"""
|
215 |
|
216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
217 |
|
218 |
-
|
219 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
220 |
|
221 |
def create_gradio_interface():
|
222 |
analyzer = IridologyAnalyzer()
|
|
|
13 |
def __init__(self):
|
14 |
print("Inicializando analisador avançado...")
|
15 |
|
16 |
+
# [Previous initialization code remains the same...]
|
17 |
+
|
18 |
+
def _preprocess_image(self, image):
|
19 |
+
"""Pré-processamento da imagem."""
|
20 |
+
if isinstance(image, Image.Image):
|
21 |
+
image = np.array(image)
|
22 |
+
|
23 |
+
if len(image.shape) == 3:
|
24 |
+
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
|
25 |
+
else:
|
26 |
+
gray = image
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
+
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(16,16))
|
29 |
+
enhanced = clahe.apply(gray)
|
30 |
+
enhanced = cv2.fastNlMeansDenoising(enhanced, None, h=10, templateWindowSize=7, searchWindowSize=21)
|
31 |
+
|
32 |
+
return enhanced, image
|
33 |
+
|
34 |
+
def _analyze_texture(self, image, enhanced):
|
35 |
+
"""Análise de textura usando GLCM."""
|
36 |
+
glcm = graycomatrix(enhanced,
|
37 |
+
distances=[1, 2, 3],
|
38 |
+
angles=[0, np.pi/4, np.pi/2, 3*np.pi/4],
|
39 |
+
symmetric=True,
|
40 |
+
normed=True)
|
41 |
+
|
42 |
+
contrast = graycoprops(glcm, 'contrast').mean()
|
43 |
+
dissimilarity = graycoprops(glcm, 'dissimilarity').mean()
|
44 |
+
homogeneity = graycoprops(glcm, 'homogeneity').mean()
|
45 |
+
energy = graycoprops(glcm, 'energy').mean()
|
46 |
+
correlation = graycoprops(glcm, 'correlation').mean()
|
47 |
+
|
48 |
+
texture_complexity = (contrast * dissimilarity) / (homogeneity * energy)
|
49 |
+
|
50 |
+
if texture_complexity > 100:
|
51 |
+
return "Textura muito complexa e detalhada", texture_complexity
|
52 |
+
elif texture_complexity > 50:
|
53 |
+
return "Textura moderadamente complexa", texture_complexity
|
54 |
+
else:
|
55 |
+
return "Textura simples ou uniforme", texture_complexity
|
56 |
+
|
57 |
+
def _analyze_color(self, image, enhanced):
|
58 |
+
"""Análise de cor."""
|
59 |
+
if len(image.shape) == 3:
|
60 |
+
hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
|
61 |
+
lab = cv2.cvtColor(image, cv2.COLOR_RGB2LAB)
|
62 |
|
63 |
+
hue_entropy = entropy(hsv[:,:,0].flatten())
|
64 |
+
sat_entropy = entropy(hsv[:,:,1].flatten())
|
65 |
+
light_entropy = entropy(lab[:,:,0].flatten())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
|
67 |
+
color_complexity = (hue_entropy * sat_entropy * light_entropy) ** (1/3)
|
|
|
|
|
68 |
|
69 |
+
if color_complexity > 4:
|
70 |
+
return "Coloração muito rica e complexa", color_complexity
|
71 |
+
elif color_complexity > 2:
|
72 |
+
return "Coloração moderadamente complexa", color_complexity
|
73 |
+
else:
|
74 |
+
return "Coloração simples ou uniforme", color_complexity
|
75 |
+
return "Não foi possível analisar coloração", 0
|
76 |
|
77 |
+
def _analyze_spots(self, image, enhanced):
|
78 |
+
"""Análise de manchas."""
|
79 |
+
spots = []
|
80 |
+
for scale in [0.5, 1.0, 2.0]:
|
81 |
+
scaled = cv2.resize(enhanced, None, fx=scale, fy=scale)
|
82 |
|
83 |
+
local_thresh = cv2.adaptiveThreshold(scaled, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
|
84 |
+
cv2.THRESH_BINARY, 11, 2)
|
85 |
+
global_thresh = cv2.threshold(scaled, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
|
86 |
|
87 |
+
combined = cv2.bitwise_and(local_thresh, global_thresh)
|
88 |
+
contours, _ = cv2.findContours(combined, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
|
89 |
+
valid_spots = [c for c in contours if 10*scale < cv2.contourArea(c) < 100*scale]
|
90 |
+
spots.extend(valid_spots)
|
91 |
+
|
92 |
+
if not spots:
|
93 |
+
return "Nenhuma mancha significativa detectada", 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
|
95 |
+
spot_complexity = len(spots) * np.std([cv2.contourArea(s) for s in spots])
|
96 |
+
|
97 |
+
if spot_complexity > 1000:
|
98 |
+
return f"Padrão complexo de manchas ({len(spots)} detectadas)", spot_complexity
|
99 |
+
elif spot_complexity > 500:
|
100 |
+
return f"Padrão moderado de manchas ({len(spots)} detectadas)", spot_complexity
|
101 |
+
else:
|
102 |
+
return f"Padrão simples de manchas ({len(spots)} detectadas)", spot_complexity
|
103 |
+
|
104 |
+
def _analyze_rings(self, image, enhanced):
|
105 |
+
"""Análise de anéis."""
|
106 |
+
circles = cv2.HoughCircles(enhanced, cv2.HOUGH_GRADIENT, 1,
|
107 |
+
minDist=20,
|
108 |
+
param1=50,
|
109 |
+
param2=30,
|
110 |
+
minRadius=10,
|
111 |
+
maxRadius=30)
|
112 |
+
|
113 |
+
if circles is None:
|
114 |
+
return "Nenhum anel significativo detectado", 0
|
115 |
|
116 |
+
circles = np.uint16(np.around(circles[0]))
|
117 |
+
concentricity = np.std([c[2] for c in circles]) / np.mean([c[2] for c in circles])
|
118 |
+
|
119 |
+
if concentricity < 0.1:
|
120 |
+
return f"Anéis altamente concêntricos ({len(circles)} detectados)", 1/concentricity
|
121 |
+
elif concentricity < 0.2:
|
122 |
+
return f"Anéis moderadamente concêntricos ({len(circles)} detectados)", 1/concentricity
|
123 |
+
else:
|
124 |
+
return f"Anéis não concêntricos ({len(circles)} detectados)", 1/concentricity
|
125 |
+
|
126 |
+
def _analyze_pupil(self, image, enhanced):
|
127 |
+
"""Análise da pupila."""
|
128 |
+
return self._analyze_clarity(image, enhanced)
|
129 |
+
|
130 |
+
def _analyze_lines(self, image, enhanced):
|
131 |
+
"""Análise de linhas."""
|
132 |
+
edges = cv2.Canny(enhanced, 50, 150, apertureSize=3)
|
133 |
+
lines = cv2.HoughLines(edges, 1, np.pi/180, 100)
|
134 |
+
|
135 |
+
if lines is None:
|
136 |
+
return "Poucas linhas radiais detectadas", 0
|
137 |
+
|
138 |
+
angles = [line[0][1] for line in lines]
|
139 |
+
angle_std = np.std(angles)
|
140 |
+
|
141 |
+
if angle_std < 0.2:
|
142 |
+
return f"Linhas radiais bem organizadas ({len(lines)} detectadas)", 1/angle_std
|
143 |
+
elif angle_std < 0.4:
|
144 |
+
return f"Linhas radiais moderadamente organizadas ({len(lines)} detectadas)", 1/angle_std
|
145 |
+
else:
|
146 |
+
return f"Linhas radiais irregulares ({len(lines)} detectadas)", 1/angle_std
|
147 |
+
|
148 |
+
def _analyze_pigmentation(self, image, enhanced):
|
149 |
+
"""Análise de pigmentação."""
|
150 |
+
return self._analyze_color(image, enhanced)
|
151 |
+
|
152 |
+
def _analyze_clarity(self, image, enhanced):
|
153 |
+
"""Análise de clareza."""
|
154 |
+
lap_var = cv2.Laplacian(enhanced, cv2.CV_64F).var()
|
155 |
+
dft = cv2.dft(np.float32(enhanced), flags=cv2.DFT_COMPLEX_OUTPUT)
|
156 |
+
dft_shift = np.fft.fftshift(dft)
|
157 |
+
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0], dft_shift[:,:,1]))
|
158 |
+
|
159 |
+
freq_energy = np.sum(magnitude_spectrum) / (enhanced.shape[0] * enhanced.shape[1])
|
160 |
+
clarity_index = np.sqrt(lap_var * freq_energy)
|
161 |
+
|
162 |
+
if clarity_index > 1000:
|
163 |
+
return "Clareza excepcional", clarity_index
|
164 |
+
elif clarity_index > 500:
|
165 |
+
return "Alta clareza", clarity_index
|
166 |
+
elif clarity_index > 100:
|
167 |
+
return "Clareza moderada", clarity_index
|
168 |
+
else:
|
169 |
+
return "Baixa clareza", clarity_index
|
170 |
+
|
171 |
+
def _analyze_tissue(self, image, enhanced):
|
172 |
+
"""Análise do tecido."""
|
173 |
+
return self._analyze_texture(image, enhanced)
|
174 |
+
|
175 |
+
def _analyze_white_marks(self, image, enhanced):
|
176 |
+
"""Análise de marcas brancas."""
|
177 |
+
return self._analyze_spots(image, enhanced)
|
178 |
+
|
179 |
+
def _analyze_fibers(self, image, enhanced):
|
180 |
+
"""Análise de fibras."""
|
181 |
+
return self._analyze_lines(image, enhanced)
|
182 |
+
|
183 |
+
def _analyze_border(self, image, enhanced):
|
184 |
+
"""Análise da borda."""
|
185 |
+
return self._analyze_rings(image, enhanced)
|
186 |
+
|
187 |
+
# [Previous comprehensive_analysis method remains the same...]
|
188 |
|
189 |
def create_gradio_interface():
|
190 |
analyzer = IridologyAnalyzer()
|