IridologyAnalyzer / analisador_iridologico.py
DHEIVER's picture
Rename app.py to analisador_iridologico.py
d39e689 verified
raw
history blame
12.7 kB
import cv2
import numpy as np
from PIL import Image
import io
from collections import defaultdict
from scipy import ndimage
from skimage.feature import graycomatrix, graycoprops
from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification
import torch
class AnalisadorIridologicoNLP:
def __init__(self):
modelo = "neuralmind/bert-base-portuguese-cased"
self.tokenizer = AutoTokenizer.from_pretrained(modelo)
self.model = AutoModelForSequenceClassification.from_pretrained(modelo)
self.referencias = self._definir_referencias()
def _definir_referencias(self):
return {
'pupila': {
'tamanho': {
'grande': 'Indica possível estresse do sistema nervoso ou fadiga adrenal',
'pequena': 'Pode indicar tensão nervosa ou hiperatividade',
'normal': 'Sistema nervoso em equilíbrio'
},
'forma': {
'irregular': 'Possível desequilíbrio no sistema nervoso autônomo',
'regular': 'Boa regulação do sistema nervoso'
}
},
'iris': {
'densidade': {
'alta': 'Boa integridade do tecido iridiano',
'baixa': 'Possível fragilidade tecidual',
'media': 'Integridade tecidual normal'
},
'textura': {
'homogenea': 'Tecidos em bom estado',
'irregular': 'Possíveis alterações teciduais',
'mista': 'Variações na qualidade tecidual'
}
},
'collarette': {
'regularidade': {
'alta': 'Boa integridade do anel de contração',
'baixa': 'Possível comprometimento estrutural',
'media': 'Estrutura em condições normais'
},
'circularidade': {
'alta': 'Boa formação estrutural',
'baixa': 'Possível alteração na formação',
'media': 'Formação estrutural adequada'
}
}
}
def classificar_caracteristica(self, valor, tipo, subtipo):
if tipo == 'pupila':
if subtipo == 'tamanho':
if valor < 25: return 'pequena'
elif valor > 45: return 'grande'
else: return 'normal'
elif subtipo == 'forma':
return 'regular' if valor > 0.85 else 'irregular'
elif tipo == 'iris':
if subtipo == 'densidade':
if valor < 0.4: return 'baixa'
elif valor > 0.7: return 'alta'
else: return 'media'
elif subtipo == 'textura':
if valor < 0.3: return 'irregular'
elif valor > 0.6: return 'homogenea'
else: return 'mista'
elif tipo == 'collarette':
if subtipo == 'regularidade':
if valor < 300: return 'alta'
elif valor > 700: return 'baixa'
else: return 'media'
elif subtipo == 'circularidade':
if valor < 0.7: return 'baixa'
elif valor > 0.9: return 'alta'
else: return 'media'
return 'indefinido'
def gerar_interpretacao(self, metricas):
interpretacao = []
if 'pupila' in metricas:
tamanho = self.classificar_caracteristica(
metricas['pupila']['raio'],
'pupila',
'tamanho'
)
forma = self.classificar_caracteristica(
metricas['pupila']['circularidade'],
'pupila',
'forma'
)
interpretacao.append(f"Pupila: {self.referencias['pupila']['tamanho'][tamanho]}")
interpretacao.append(f"Forma pupilar: {self.referencias['pupila']['forma'][forma]}")
if 'iris' in metricas:
densidade = self.classificar_caracteristica(
metricas['iris']['densidade_media'],
'iris',
'densidade'
)
textura = self.classificar_caracteristica(
metricas['iris']['homogeneidade'],
'iris',
'textura'
)
interpretacao.append(f"Íris: {self.referencias['iris']['densidade'][densidade]}")
interpretacao.append(f"Textura: {self.referencias['iris']['textura'][textura]}")
if 'collarette' in metricas:
regularidade = self.classificar_caracteristica(
metricas['collarette']['regularidade'],
'collarette',
'regularidade'
)
circularidade = self.classificar_caracteristica(
metricas['collarette']['circularidade'],
'collarette',
'circularidade'
)
interpretacao.append(f"Collarette: {self.referencias['collarette']['regularidade'][regularidade]}")
interpretacao.append(f"Estrutura: {self.referencias['collarette']['circularidade'][circularidade]}")
texto_interpretacao = "\n".join(interpretacao)
inputs = self.tokenizer(
texto_interpretacao,
return_tensors="pt",
padding=True,
truncation=True,
max_length=512
)
with torch.no_grad():
outputs = self.model(**inputs)
refined_text = self.refinar_texto(texto_interpretacao, outputs.logits)
return refined_text
def refinar_texto(self, texto, logits):
sentencas = texto.split("\n")
refined_sentencas = [f"• {s}" for s in sentencas if len(s.strip()) > 0]
return "\n".join(refined_sentencas)
# Funções de pré-processamento, detecção e análise
def pre_processar_imagem(imagem):
lab = cv2.cvtColor(imagem, cv2.COLOR_RGB2LAB)
l, a, b = cv2.split(lab)
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
l = clahe.apply(l)
lab = cv2.merge((l,a,b))
imagem_melhorada = cv2.cvtColor(lab, cv2.COLOR_LAB2RGB)
imagem_melhorada = cv2.GaussianBlur(imagem_melhorada, (5, 5), 0)
return imagem_melhorada
def detectar_esclera(imagem):
hsv = cv2.cvtColor(imagem, cv2.COLOR_RGB2HSV)
lower_white = np.array([0, 0, 180])
upper_white = np.array([180, 30, 255])
mask_esclera = cv2.inRange(hsv, lower_white, upper_white)
kernel = np.ones((5,5), np.uint8)
mask_esclera = cv2.morphologyEx(mask_esclera, cv2.MORPH_OPEN, kernel)
mask_esclera = cv2.morphologyEx(mask_esclera, cv2.MORPH_CLOSE, kernel)
return mask_esclera
def detectar_iris_pupila(imagem, mask_esclera):
gray = cv2.cvtColor(imagem, cv2.COLOR_RGB2GRAY)
mask_olho = cv2.bitwise_not(mask_esclera)
eye_region = cv2.bitwise_and(gray, gray, mask=mask_olho)
edges = cv2.Canny(eye_region, 30, 60)
iris_circles = cv2.HoughCircles(
edges,
cv2.HOUGH_GRADIENT,
dp=1,
minDist=100,
param1=50,
param2=30,
minRadius=80,
maxRadius=150
)
if iris_circles is not None:
iris_circles = np.uint16(np.around(iris_circles))
ix, iy, ir = iris_circles[0][0]
mask_iris = np.zeros_like(gray)
cv2.circle(mask_iris, (ix, iy), ir, 255, -1)
iris_region = cv2.bitwise_and(gray, gray, mask=mask_iris)
thresh = cv2.adaptiveThreshold(
iris_region,
255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV,
11,
2
)
pupil_circles = cv2.HoughCircles(
thresh,
cv2.HOUGH_GRADIENT,
dp=1,
minDist=50,
param1=50,
param2=25,
minRadius=20,
maxRadius=50
)
if pupil_circles is not None:
pupil_circles = np.uint16(np.around(pupil_circles))
px, py, pr = pupil_circles[0][0]
return (ix, iy, ir), (px, py, pr)
return None, None
def analisar_textura_setorial(imagem, iris_info, pupil_info):
if iris_info is None or pupil_info is None:
return {}
ix, iy, ir = iris_info
px, py, pr = pupil_info
gray = cv2.cvtColor(imagem, cv2.COLOR_RGB2GRAY)
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(4, 4))
gray = clahe.apply(gray)
mask_iris = np.zeros_like(gray)
cv2.circle(mask_iris, (ix, iy), int(ir * 0.98), 255, -1)
cv2.circle(mask_iris, (px, py), int(pr * 1.02), 0, -1)
setores = {}
for i in range(12):
ang_inicio = i * 30
ang_fim = (i + 1) * 30
mask_setor = np.zeros_like(gray)
cv2.ellipse(mask_setor,
(ix, iy),
(ir, ir),
0,
ang_inicio,
ang_fim,
255,
-1)
mask_final = cv2.bitwise_and(mask_iris, mask_setor)
kernel = np.ones((2, 2), np.uint8)
mask_final = cv2.morphologyEx(mask_final, cv2.MORPH_OPEN, kernel)
setor_roi = cv2.bitwise_and(gray, gray, mask=mask_final)
non_zero = setor_roi[setor_roi > 0]
if len(non_zero) > 100:
non_zero = ((non_zero - non_zero.min()) /
(non_zero.max() - non_zero.min() + 1e-8) * 15).astype(np.uint8)
tamanho_janela = int(np.sqrt(len(non_zero)))
if tamanho_janela > 1:
matriz_2d = non_zero[:tamanho_janela**2].reshape(tamanho_janela, tamanho_janela)
try:
glcm = graycomatrix(matriz_2d,
distances=[1],
angles=[0, np.pi/4],
levels=16,
symmetric=True,
normed=True)
contraste = np.mean(graycoprops(glcm, 'contrast'))
homogeneidade = np.mean(graycoprops(glcm, 'homogeneity'))
setores[f"setor_{i+1}"] = {
"contraste": float(contraste),
"homogeneidade": float(homogeneidade),
"media": float(np.mean(non_zero)),
"std": float(np.std(non_zero))
}
except Exception as e:
setores[f"setor_{i+1}"] = {
"contraste": 0.0,
"homogeneidade": 1.0,
"media": 0.0,
"std": 0.0
}
else:
setores[f"setor_{i+1}"] = {
"contraste": 0.0,
"homogeneidade": 1.0,
"media": 0.0,
"std": 0.0
}
else:
setores[f"setor_{i+1}"] = {
"contraste": 0.0,
"homogeneidade": 1.0,
"media": 0.0,
"std": 0.0
}
return setores
def validar_metricas(metricas):
metricas_validadas = {}
if 'pupila' in metricas:
raio = metricas['pupila'].get('raio', 0)
circularidade = metricas['pupila'].get('circularidade', 0)
if raio <= 0 or raio > 100:
raio = 35
if circularidade <= 0 or circularidade > 1:
circularidade = 0.85
metricas_validadas['pupila'] = {
'raio': raio,
'circularidade': circularidade
}
if 'iris' in metricas:
densidade = metricas['iris'].get('densidade_media', 0)
homogeneidade = metricas['iris'].get('homogeneidade', 0)
if densidade < 0:
densidade = 0.5
if homogeneidade < 0 or homogeneidade > 1:
homogeneidade = 0.5
metricas_validadas['iris'] = {
'densidade_media': densidade,
'homogeneidade': homogeneidade
}
if 'collarette' in metricas and metricas['collarette']:
regularidade = metricas['collarette'].get('regularidade', 0)
circularidade = metricas['collarette'].get('circularidade', 0)
if regularidade < 0:
regularidade = 300
if circularidade < 0 or circularidade > 1:
circularidade = 0.85
metricas_validadas['collarette'] = {
'regularidade': regularidade,
'circularidade': circularidade
}
return metricas_validadas