Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -294,7 +294,7 @@ def detectar_iris_pupila(imagem, mask_esclera):
|
|
294 |
|
295 |
def analisar_textura_setorial(imagem, iris_info, pupil_info):
|
296 |
"""
|
297 |
-
Analisa a textura da íris por setores
|
298 |
"""
|
299 |
if iris_info is None or pupil_info is None:
|
300 |
return {}
|
@@ -302,21 +302,25 @@ def analisar_textura_setorial(imagem, iris_info, pupil_info):
|
|
302 |
ix, iy, ir = iris_info
|
303 |
px, py, pr = pupil_info
|
304 |
|
305 |
-
# Converter para escala de cinza
|
306 |
gray = cv2.cvtColor(imagem, cv2.COLOR_RGB2GRAY)
|
307 |
|
308 |
-
#
|
|
|
|
|
|
|
|
|
309 |
mask_iris = np.zeros_like(gray)
|
310 |
-
cv2.circle(mask_iris, (ix, iy), ir, 255, -1)
|
311 |
-
cv2.circle(mask_iris, (px, py), pr, 0, -1)
|
312 |
|
313 |
-
# Dividir em 12 setores
|
314 |
setores = {}
|
315 |
for i in range(12):
|
316 |
ang_inicio = i * 30
|
317 |
ang_fim = (i + 1) * 30
|
318 |
|
319 |
-
# Criar máscara do setor
|
320 |
mask_setor = np.zeros_like(gray)
|
321 |
cv2.ellipse(mask_setor,
|
322 |
(ix, iy),
|
@@ -327,28 +331,71 @@ def analisar_textura_setorial(imagem, iris_info, pupil_info):
|
|
327 |
255,
|
328 |
-1)
|
329 |
|
330 |
-
# Combinar máscaras
|
|
|
331 |
mask_final = cv2.bitwise_and(mask_iris, mask_setor)
|
|
|
332 |
|
333 |
# Extrair região do setor
|
334 |
setor_roi = cv2.bitwise_and(gray, gray, mask=mask_final)
|
335 |
|
336 |
-
# Análise de textura
|
337 |
-
non_zero = setor_roi[setor_roi
|
338 |
-
if len(non_zero) >
|
339 |
-
#
|
340 |
-
|
341 |
-
|
342 |
-
glcm = graycomatrix(non_zero.reshape(-1, 1), distances, angles,
|
343 |
-
symmetric=True, normed=True)
|
344 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
345 |
setores[f"setor_{i+1}"] = {
|
346 |
-
"media":
|
347 |
-
"std":
|
348 |
-
"contraste":
|
349 |
-
"homogeneidade":
|
350 |
-
"energia":
|
351 |
-
"correlacao":
|
|
|
352 |
}
|
353 |
|
354 |
return setores
|
@@ -414,6 +461,62 @@ def avaliar_circularidade(mask):
|
|
414 |
return circularity
|
415 |
return 0
|
416 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
417 |
def criar_interface():
|
418 |
"""
|
419 |
Cria interface moderna do Gradio
|
@@ -472,7 +575,8 @@ def criar_interface():
|
|
472 |
'collarette': info_collarette
|
473 |
}
|
474 |
|
475 |
-
#
|
|
|
476 |
interpretacao_nlp = integrar_analise_nlp(metricas)
|
477 |
|
478 |
# Desenhar esclera
|
|
|
294 |
|
295 |
def analisar_textura_setorial(imagem, iris_info, pupil_info):
|
296 |
"""
|
297 |
+
Analisa a textura da íris por setores com correções e melhorias
|
298 |
"""
|
299 |
if iris_info is None or pupil_info is None:
|
300 |
return {}
|
|
|
302 |
ix, iy, ir = iris_info
|
303 |
px, py, pr = pupil_info
|
304 |
|
305 |
+
# Converter para escala de cinza com preservação de contraste
|
306 |
gray = cv2.cvtColor(imagem, cv2.COLOR_RGB2GRAY)
|
307 |
|
308 |
+
# Equalização adaptativa do histograma
|
309 |
+
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
|
310 |
+
gray = clahe.apply(gray)
|
311 |
+
|
312 |
+
# Criar máscara anelar da íris com margem de segurança
|
313 |
mask_iris = np.zeros_like(gray)
|
314 |
+
cv2.circle(mask_iris, (ix, iy), int(ir * 0.95), 255, -1) # Reduzir raio em 5%
|
315 |
+
cv2.circle(mask_iris, (px, py), int(pr * 1.05), 0, -1) # Aumentar raio em 5%
|
316 |
|
317 |
+
# Dividir em 12 setores
|
318 |
setores = {}
|
319 |
for i in range(12):
|
320 |
ang_inicio = i * 30
|
321 |
ang_fim = (i + 1) * 30
|
322 |
|
323 |
+
# Criar máscara do setor com ângulos precisos
|
324 |
mask_setor = np.zeros_like(gray)
|
325 |
cv2.ellipse(mask_setor,
|
326 |
(ix, iy),
|
|
|
331 |
255,
|
332 |
-1)
|
333 |
|
334 |
+
# Combinar máscaras com operação morfológica
|
335 |
+
kernel = np.ones((3,3), np.uint8)
|
336 |
mask_final = cv2.bitwise_and(mask_iris, mask_setor)
|
337 |
+
mask_final = cv2.morphologyEx(mask_final, cv2.MORPH_OPEN, kernel)
|
338 |
|
339 |
# Extrair região do setor
|
340 |
setor_roi = cv2.bitwise_and(gray, gray, mask=mask_final)
|
341 |
|
342 |
+
# Análise de textura melhorada
|
343 |
+
non_zero = setor_roi[setor_roi > 0]
|
344 |
+
if len(non_zero) > 100: # Garantir amostra significativa
|
345 |
+
# Normalizar valores
|
346 |
+
non_zero = ((non_zero - non_zero.min()) /
|
347 |
+
(non_zero.max() - non_zero.min() + 1e-8) * 255).astype(np.uint8)
|
|
|
|
|
348 |
|
349 |
+
# Reshape para matriz 2D para GLCM
|
350 |
+
tamanho_janela = int(np.sqrt(len(non_zero)))
|
351 |
+
if tamanho_janela > 1:
|
352 |
+
matriz_2d = non_zero[:tamanho_janela**2].reshape(tamanho_janela, tamanho_janela)
|
353 |
+
|
354 |
+
# Calcular GLCM com múltiplas distâncias e ângulos
|
355 |
+
distances = [1, 2, 3]
|
356 |
+
angles = [0, np.pi/4, np.pi/2, 3*np.pi/4]
|
357 |
+
glcm = graycomatrix(matriz_2d, distances, angles,
|
358 |
+
symmetric=True, normed=True)
|
359 |
+
|
360 |
+
# Calcular propriedades médias
|
361 |
+
contraste = np.mean(graycoprops(glcm, 'contrast'))
|
362 |
+
homogeneidade = np.mean(graycoprops(glcm, 'homogeneity'))
|
363 |
+
energia = np.mean(graycoprops(glcm, 'energy'))
|
364 |
+
correlacao = np.mean(graycoprops(glcm, 'correlation'))
|
365 |
+
|
366 |
+
# Análise de gradiente
|
367 |
+
sobelx = cv2.Sobel(matriz_2d, cv2.CV_64F, 1, 0, ksize=3)
|
368 |
+
sobely = cv2.Sobel(matriz_2d, cv2.CV_64F, 0, 1, ksize=3)
|
369 |
+
gradiente = np.mean(np.sqrt(sobelx**2 + sobely**2))
|
370 |
+
|
371 |
+
setores[f"setor_{i+1}"] = {
|
372 |
+
"media": np.mean(non_zero),
|
373 |
+
"std": np.std(non_zero),
|
374 |
+
"contraste": float(contraste),
|
375 |
+
"homogeneidade": float(homogeneidade),
|
376 |
+
"energia": float(energia),
|
377 |
+
"correlacao": float(correlacao),
|
378 |
+
"gradiente": float(gradiente)
|
379 |
+
}
|
380 |
+
else:
|
381 |
+
setores[f"setor_{i+1}"] = {
|
382 |
+
"media": np.mean(non_zero),
|
383 |
+
"std": np.std(non_zero),
|
384 |
+
"contraste": 0.0,
|
385 |
+
"homogeneidade": 1.0,
|
386 |
+
"energia": 1.0,
|
387 |
+
"correlacao": 0.0,
|
388 |
+
"gradiente": 0.0
|
389 |
+
}
|
390 |
+
else:
|
391 |
setores[f"setor_{i+1}"] = {
|
392 |
+
"media": 0.0,
|
393 |
+
"std": 0.0,
|
394 |
+
"contraste": 0.0,
|
395 |
+
"homogeneidade": 1.0,
|
396 |
+
"energia": 1.0,
|
397 |
+
"correlacao": 0.0,
|
398 |
+
"gradiente": 0.0
|
399 |
}
|
400 |
|
401 |
return setores
|
|
|
461 |
return circularity
|
462 |
return 0
|
463 |
|
464 |
+
def validar_metricas(metricas):
|
465 |
+
"""
|
466 |
+
Valida e ajusta as métricas antes da interpretação
|
467 |
+
"""
|
468 |
+
metricas_validadas = {}
|
469 |
+
|
470 |
+
# Validar pupila
|
471 |
+
if 'pupila' in metricas:
|
472 |
+
raio = metricas['pupila'].get('raio', 0)
|
473 |
+
circularidade = metricas['pupila'].get('circularidade', 0)
|
474 |
+
|
475 |
+
# Ajustar valores inválidos
|
476 |
+
if raio <= 0 or raio > 100:
|
477 |
+
raio = 35 # valor médio típico
|
478 |
+
if circularidade <= 0 or circularidade > 1:
|
479 |
+
circularidade = 0.85 # valor típico
|
480 |
+
|
481 |
+
metricas_validadas['pupila'] = {
|
482 |
+
'raio': raio,
|
483 |
+
'circularidade': circularidade
|
484 |
+
}
|
485 |
+
|
486 |
+
# Validar íris
|
487 |
+
if 'iris' in metricas:
|
488 |
+
densidade = metricas['iris'].get('densidade_media', 0)
|
489 |
+
homogeneidade = metricas['iris'].get('homogeneidade', 0)
|
490 |
+
|
491 |
+
# Ajustar valores inválidos
|
492 |
+
if densidade < 0:
|
493 |
+
densidade = 0.5 # valor médio típico
|
494 |
+
if homogeneidade < 0 or homogeneidade > 1:
|
495 |
+
homogeneidade = 0.5 # valor médio
|
496 |
+
|
497 |
+
metricas_validadas['iris'] = {
|
498 |
+
'densidade_media': densidade,
|
499 |
+
'homogeneidade': homogeneidade
|
500 |
+
}
|
501 |
+
|
502 |
+
# Validar collarette
|
503 |
+
if 'collarette' in metricas and metricas['collarette']:
|
504 |
+
regularidade = metricas['collarette'].get('regularidade', 0)
|
505 |
+
circularidade = metricas['collarette'].get('circularidade', 0)
|
506 |
+
|
507 |
+
# Ajustar valores inválidos
|
508 |
+
if regularidade < 0:
|
509 |
+
regularidade = 300 # valor típico
|
510 |
+
if circularidade < 0 or circularidade > 1:
|
511 |
+
circularidade = 0.85 # valor típico
|
512 |
+
|
513 |
+
metricas_validadas['collarette'] = {
|
514 |
+
'regularidade': regularidade,
|
515 |
+
'circularidade': circularidade
|
516 |
+
}
|
517 |
+
|
518 |
+
return metricas_validadas
|
519 |
+
|
520 |
def criar_interface():
|
521 |
"""
|
522 |
Cria interface moderna do Gradio
|
|
|
575 |
'collarette': info_collarette
|
576 |
}
|
577 |
|
578 |
+
# Na função processar_imagem, antes de chamar integrar_analise_nlp:
|
579 |
+
metricas = validar_metricas(metricas)
|
580 |
interpretacao_nlp = integrar_analise_nlp(metricas)
|
581 |
|
582 |
# Desenhar esclera
|