Update app.py
Browse files
app.py
CHANGED
@@ -18,7 +18,7 @@ def ordenar_e_preprocessar_imagem(img, modelo):
|
|
18 |
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
19 |
h, w = img.shape
|
20 |
img_out = preprocessar_imagem(img, modelo)
|
21 |
-
return img_out
|
22 |
|
23 |
# Função para pré-processar a imagem com base no modelo selecionado
|
24 |
def preprocessar_imagem(img, modelo='SE-RegUNet 4GF'):
|
@@ -67,6 +67,9 @@ def processar_imagem_de_entrada(img, modelo, pipe, salvar_resultado=False):
|
|
67 |
# Coloque o modelo na GPU (se disponível) e configure-o para modo de avaliação
|
68 |
pipe = pipe.to(device).eval()
|
69 |
|
|
|
|
|
|
|
70 |
# Pré-processe a imagem e obtenha informações de dimensão
|
71 |
img, h, w, ori_gray, ori = ordenar_e_preprocessar_imagem(img, modelo)
|
72 |
|
@@ -79,6 +82,10 @@ def processar_imagem_de_entrada(img, modelo, pipe, salvar_resultado=False):
|
|
79 |
img = torch.cat([img, img], dim=0)
|
80 |
logit = np.round(torch.softmax(pipe.forward(img), dim=1).detach().cpu().numpy()[0, 0]).astype(np.uint8)
|
81 |
|
|
|
|
|
|
|
|
|
82 |
# Redimensione o resultado, se necessário
|
83 |
if h != 512 or w != 512:
|
84 |
logit = cv2.resize(logit, (h, w))
|
@@ -95,11 +102,13 @@ def processar_imagem_de_entrada(img, modelo, pipe, salvar_resultado=False):
|
|
95 |
nome_arquivo = os.path.join(caminho_salvar_resultado, f'resultado_{int(time.time())}.png')
|
96 |
cv2.imwrite(nome_arquivo, img_out)
|
97 |
|
98 |
-
return img_out
|
99 |
|
100 |
except Exception as e:
|
101 |
# Em caso de erro, retorne uma mensagem de erro
|
102 |
-
return str(e)
|
|
|
|
|
103 |
|
104 |
# Carregar modelos pré-treinados
|
105 |
models = {
|
@@ -111,11 +120,68 @@ models = {
|
|
111 |
'UNet3+': torch.jit.load('./model/UNet3plus.pt'),
|
112 |
}
|
113 |
|
114 |
-
|
115 |
-
|
|
|
|
|
|
|
|
|
116 |
model = models[modelo]
|
117 |
-
img_out = processar_imagem_de_entrada(img, modelo, model)
|
118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
|
120 |
# Criar a interface Gradio
|
121 |
my_app = gr.Interface(
|
@@ -123,8 +189,15 @@ my_app = gr.Interface(
|
|
123 |
inputs=[
|
124 |
gr.inputs.Image(label="Angiograma:", shape=(512, 512)),
|
125 |
gr.inputs.Dropdown(['SE-RegUNet 4GF','SE-RegUNet 16GF', 'AngioNet', 'EffUNet++ B5', 'Reg-SA-UNet++', 'UNet3+'], label='Modelo', default='SE-RegUNet 4GF'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
],
|
127 |
-
outputs=gr.outputs.Image(type="numpy", label="Imagem de Saída"),
|
128 |
title="Segmentação de Angiograma Coronariano",
|
129 |
description="Esta aplicação segmenta angiogramas coronarianos usando modelos de segmentação pré-treinados.",
|
130 |
theme="default",
|
|
|
18 |
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
19 |
h, w = img.shape
|
20 |
img_out = preprocessar_imagem(img, modelo)
|
21 |
+
return img_out, h, w, img, ori
|
22 |
|
23 |
# Função para pré-processar a imagem com base no modelo selecionado
|
24 |
def preprocessar_imagem(img, modelo='SE-RegUNet 4GF'):
|
|
|
67 |
# Coloque o modelo na GPU (se disponível) e configure-o para modo de avaliação
|
68 |
pipe = pipe.to(device).eval()
|
69 |
|
70 |
+
# Registre o tempo de início
|
71 |
+
start = time.time()
|
72 |
+
|
73 |
# Pré-processe a imagem e obtenha informações de dimensão
|
74 |
img, h, w, ori_gray, ori = ordenar_e_preprocessar_imagem(img, modelo)
|
75 |
|
|
|
82 |
img = torch.cat([img, img], dim=0)
|
83 |
logit = np.round(torch.softmax(pipe.forward(img), dim=1).detach().cpu().numpy()[0, 0]).astype(np.uint8)
|
84 |
|
85 |
+
# Calcule o tempo decorrido
|
86 |
+
spent = time.time() - start
|
87 |
+
spent = f"{spent:.3f} segundos"
|
88 |
+
|
89 |
# Redimensione o resultado, se necessário
|
90 |
if h != 512 or w != 512:
|
91 |
logit = cv2.resize(logit, (h, w))
|
|
|
102 |
nome_arquivo = os.path.join(caminho_salvar_resultado, f'resultado_{int(time.time())}.png')
|
103 |
cv2.imwrite(nome_arquivo, img_out)
|
104 |
|
105 |
+
return spent, img_out
|
106 |
|
107 |
except Exception as e:
|
108 |
# Em caso de erro, retorne uma mensagem de erro
|
109 |
+
return str(e), None
|
110 |
+
|
111 |
+
|
112 |
|
113 |
# Carregar modelos pré-treinados
|
114 |
models = {
|
|
|
120 |
'UNet3+': torch.jit.load('./model/UNet3plus.pt'),
|
121 |
}
|
122 |
|
123 |
+
from scipy.spatial import distance
|
124 |
+
from scipy.ndimage import label
|
125 |
+
import numpy as np
|
126 |
+
|
127 |
+
# Adicionar a opção de salvar o resultado em um arquivo
|
128 |
+
def processar_imagem_de_entrada_wrapper(img, modelo, salvar_resultado=False):
|
129 |
model = models[modelo]
|
130 |
+
resultado, img_out = processar_imagem_de_entrada(img, modelo, model, salvar_resultado)
|
131 |
+
|
132 |
+
# Resto do código permanece inalterado
|
133 |
+
kmeans = KMeans(n_clusters=2, random_state=0)
|
134 |
+
flattened_img = img_out[:, :, 0].reshape((-1, 1))
|
135 |
+
kmeans.fit(flattened_img)
|
136 |
+
labels = kmeans.labels_
|
137 |
+
cluster_centers = kmeans.cluster_centers_
|
138 |
+
|
139 |
+
# Detecção de doenças usando K-Means
|
140 |
+
kmeans = KMeans(n_clusters=2, random_state=0)
|
141 |
+
flattened_img = img_out[:, :, 0].reshape((-1, 1)) # Use o canal de intensidade
|
142 |
+
kmeans.fit(flattened_img)
|
143 |
+
labels = kmeans.labels_
|
144 |
+
cluster_centers = kmeans.cluster_centers_
|
145 |
+
|
146 |
+
# Resto do código permanece inalterado
|
147 |
+
|
148 |
+
# Extração de características dos clusters
|
149 |
+
num_clusters = len(cluster_centers)
|
150 |
+
cluster_features = []
|
151 |
+
for i in range(num_clusters):
|
152 |
+
cluster_mask = labels == i # Create a boolean mask for the cluster
|
153 |
+
|
154 |
+
# Calcular área do cluster
|
155 |
+
area = np.sum(cluster_mask)
|
156 |
+
|
157 |
+
if area == 0: # Skip empty clusters
|
158 |
+
continue
|
159 |
+
|
160 |
+
# Calcular forma do cluster usando a relação entre área e perímetro
|
161 |
+
contours, _ = cv2.findContours(np.uint8(cluster_mask), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
162 |
+
if len(contours) > 0:
|
163 |
+
perimeter = cv2.arcLength(contours[0], True)
|
164 |
+
compactness = 4 * np.pi * area / (perimeter ** 2)
|
165 |
+
|
166 |
+
cluster_features.append({'area': area, 'compactness': compactness})
|
167 |
+
|
168 |
+
# Decidir se há doença com base nas características dos clusters
|
169 |
+
has_disease_flag = any(feature['area'] >= 200 and feature['compactness'] < 0.3 for feature in cluster_features)
|
170 |
+
|
171 |
+
# Formatar o indicador de doença como uma string
|
172 |
+
if has_disease_flag:
|
173 |
+
status_doenca = "Sim"
|
174 |
+
explanation = "A máquina detectou uma possível doença nos vasos sanguíneos."
|
175 |
+
else:
|
176 |
+
status_doenca = "Não"
|
177 |
+
explanation = "A máquina não detectou nenhuma doença nos vasos sanguíneos."
|
178 |
+
|
179 |
+
# Resto do código permanece inalterado
|
180 |
+
|
181 |
+
return resultado, img_out, status_doenca, explanation, f"{num_analises} análises realizadas"
|
182 |
+
|
183 |
+
# Inicializar a contagem de análises
|
184 |
+
num_analises = 0
|
185 |
|
186 |
# Criar a interface Gradio
|
187 |
my_app = gr.Interface(
|
|
|
189 |
inputs=[
|
190 |
gr.inputs.Image(label="Angiograma:", shape=(512, 512)),
|
191 |
gr.inputs.Dropdown(['SE-RegUNet 4GF','SE-RegUNet 16GF', 'AngioNet', 'EffUNet++ B5', 'Reg-SA-UNet++', 'UNet3+'], label='Modelo', default='SE-RegUNet 4GF'),
|
192 |
+
gr.inputs.Checkbox(label="Salvar Resultado"),
|
193 |
+
],
|
194 |
+
outputs=[
|
195 |
+
gr.outputs.Label(label="Tempo decorrido"),
|
196 |
+
gr.outputs.Image(type="numpy", label="Imagem de Saída"),
|
197 |
+
gr.outputs.Label(label="Possui Doença?"),
|
198 |
+
gr.outputs.Label(label="Explicação"),
|
199 |
+
gr.outputs.Label(label="Análises Realizadas"),
|
200 |
],
|
|
|
201 |
title="Segmentação de Angiograma Coronariano",
|
202 |
description="Esta aplicação segmenta angiogramas coronarianos usando modelos de segmentação pré-treinados.",
|
203 |
theme="default",
|