Update app.py
Browse files
app.py
CHANGED
@@ -1,4 +1,6 @@
|
|
1 |
import os
|
|
|
|
|
2 |
import gradio as gr
|
3 |
import torch
|
4 |
import cv2
|
@@ -6,6 +8,17 @@ import numpy as np
|
|
6 |
from preprocess import unsharp_masking
|
7 |
import time
|
8 |
from sklearn.cluster import KMeans
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
# Função para pré-processar a imagem com base no modelo selecionado
|
11 |
def preprocessar_imagem(img, modelo='SE-RegUNet 4GF'):
|
@@ -39,20 +52,14 @@ def preprocessar_imagem(img, modelo='SE-RegUNet 4GF'):
|
|
39 |
|
40 |
return img_out
|
41 |
|
42 |
-
# # Função para realizar a inferência do modelo
|
43 |
-
# def inferir_modelo(img, pipe, device):
|
44 |
-
# # Faça a inferência do modelo aqui
|
45 |
-
# # Certifique-se de pré-processar a imagem, colocá-la na GPU e retornar o resultado
|
46 |
-
# # ...
|
47 |
|
48 |
-
|
49 |
-
|
50 |
-
#
|
51 |
-
|
52 |
-
# # ...
|
53 |
|
54 |
# Função para processar a imagem de entrada
|
55 |
-
def processar_imagem_de_entrada(img, modelo, pipe,
|
56 |
try:
|
57 |
# Faça uma cópia da imagem original
|
58 |
img = img.copy()
|
@@ -64,10 +71,7 @@ def processar_imagem_de_entrada(img, modelo, pipe, device, salvar_resultado=Fals
|
|
64 |
start = time.time()
|
65 |
|
66 |
# Pré-processe a imagem e obtenha informações de dimensão
|
67 |
-
img = img
|
68 |
-
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
69 |
-
h, w = img.shape
|
70 |
-
img = preprocessar_imagem(img, modelo)
|
71 |
|
72 |
# Converta a imagem para o formato esperado pelo modelo e coloque-a na GPU
|
73 |
img = torch.FloatTensor(img).unsqueeze(0).to(device)
|
@@ -90,92 +94,115 @@ def processar_imagem_de_entrada(img, modelo, pipe, device, salvar_resultado=Fals
|
|
90 |
logit = logit.astype(bool)
|
91 |
|
92 |
# Crie uma cópia da imagem original para saída e aplique a máscara
|
93 |
-
img_out =
|
94 |
img_out[logit, 0] = 255
|
|
|
|
|
|
|
|
|
|
|
95 |
|
96 |
-
|
97 |
-
kmeans = KMeans(n_clusters=2, random_state=0)
|
98 |
-
flattened_img = img_out[:, :, 0].reshape((-1, 1))
|
99 |
-
kmeans.fit(flattened_img)
|
100 |
-
labels = kmeans.labels_
|
101 |
-
cluster_centers = kmeans.cluster_centers_
|
102 |
-
|
103 |
-
# Extração de características dos clusters
|
104 |
-
num_clusters = len(cluster_centers)
|
105 |
-
cluster_features = []
|
106 |
-
for i in range(num_clusters):
|
107 |
-
cluster_mask = labels == i # Create a boolean mask for the cluster
|
108 |
-
|
109 |
-
# Calcular área do cluster
|
110 |
-
area = np.sum(cluster_mask)
|
111 |
-
|
112 |
-
if area == 0: # Skip empty clusters
|
113 |
-
continue
|
114 |
-
|
115 |
-
# Calcular forma do cluster usando a relação entre área e perímetro
|
116 |
-
contours, _ = cv2.findContours(np.uint8(cluster_mask), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
117 |
-
if len(contours) > 0:
|
118 |
-
perimeter = cv2.arcLength(contours[0], True)
|
119 |
-
compactness = 4 * np.pi * area / (perimeter ** 2)
|
120 |
-
|
121 |
-
cluster_features.append({'area': area, 'compactness': compactness})
|
122 |
-
|
123 |
-
# Decidir se há doença com base nas características dos clusters
|
124 |
-
has_disease_flag = any(feature['area'] >= 200 and feature['compactness'] < 0.3 for feature in cluster_features)
|
125 |
-
|
126 |
-
# Formatar o indicador de doença como uma string
|
127 |
-
if has_doenca_flag:
|
128 |
-
status_doenca = "Sim"
|
129 |
-
explanation = "A máquina detectou uma possível doença nos vasos sanguíneos."
|
130 |
-
else:
|
131 |
-
status_doenca = "Não"
|
132 |
-
explanation = "A máquina não detectou nenhuma doença nos vasos sanguíneos."
|
133 |
-
|
134 |
-
return spent, img_out, status_doenca, explanation
|
135 |
|
136 |
except Exception as e:
|
137 |
# Em caso de erro, retorne uma mensagem de erro
|
138 |
return str(e), None
|
139 |
|
140 |
-
# Função para carregar um modelo pré-treinado com base no nome do modelo
|
141 |
-
def carregar_modelo(modelo_nome):
|
142 |
-
return torch.jit.load(f'./model/{modelo_nome}.pt')
|
143 |
|
144 |
-
# Função principal para iniciar o aplicativo
|
145 |
-
def processar_imagem():
|
146 |
-
try:
|
147 |
-
# Configuração inicial
|
148 |
-
modelo_inicial = 'SE-RegUNet 4GF'
|
149 |
-
device = "cuda" if torch.cuda.is_available() else "cpu"
|
150 |
-
pipe = carregar_modelo(modelo_inicial)
|
151 |
-
|
152 |
-
# Criar a interface Gradio
|
153 |
-
my_app = gr.Interface(
|
154 |
-
fn=processar_imagem_de_entrada,
|
155 |
-
inputs=[
|
156 |
-
gr.inputs.Image(label="Angiograma:", shape=(512, 512)),
|
157 |
-
gr.inputs.Dropdown(['SE-RegUNet 4GF','SE-RegUNet 16GF', 'AngioNet', 'EffUNet++ B5', 'Reg-SA-UNet++', 'UNet3+'], label='Modelo', default=modelo_inicial),
|
158 |
-
gr.inputs.Checkbox(label="Salvar Resultado"),
|
159 |
-
],
|
160 |
-
outputs=[
|
161 |
-
gr.outputs.Label(label="Tempo decorrido"),
|
162 |
-
gr.outputs.Image(type="numpy", label="Imagem de Saída"),
|
163 |
-
gr.outputs.Label(label="Possui Doença?"),
|
164 |
-
gr.outputs.Label(label="Explicação"),
|
165 |
-
],
|
166 |
-
title="Segmentação de Angiograma Coronariano",
|
167 |
-
description="Esta aplicação segmenta angiogramas coronarianos usando modelos de segmentação pré-treinados.",
|
168 |
-
theme="default",
|
169 |
-
layout="vertical",
|
170 |
-
allow_flagging=False,
|
171 |
-
)
|
172 |
-
|
173 |
-
# Iniciar a interface Gradio
|
174 |
-
my_app.launch()
|
175 |
|
176 |
-
|
177 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
|
179 |
-
#
|
180 |
-
|
|
|
181 |
|
|
|
|
|
|
1 |
import os
|
2 |
+
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
|
3 |
+
|
4 |
import gradio as gr
|
5 |
import torch
|
6 |
import cv2
|
|
|
8 |
from preprocess import unsharp_masking
|
9 |
import time
|
10 |
from sklearn.cluster import KMeans
|
11 |
+
import os
|
12 |
+
|
13 |
+
device = "cuda" if torch.cuda.is_available() else "cpu"
|
14 |
+
|
15 |
+
# Função para ordenar e pré-processar a imagem de entrada
|
16 |
+
def ordenar_e_preprocessar_imagem(img, modelo):
|
17 |
+
ori = img.copy()
|
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'):
|
|
|
52 |
|
53 |
return img_out
|
54 |
|
|
|
|
|
|
|
|
|
|
|
55 |
|
56 |
+
import os
|
57 |
+
|
58 |
+
# Caminho absoluto para a pasta de salvamento
|
59 |
+
caminho_salvar_resultado = "/Segmento_de_Angio_Coronariana_v5/Salvar Resultado"
|
|
|
60 |
|
61 |
# Função para processar a imagem de entrada
|
62 |
+
def processar_imagem_de_entrada(img, modelo, pipe, salvar_resultado=False):
|
63 |
try:
|
64 |
# Faça uma cópia da imagem original
|
65 |
img = img.copy()
|
|
|
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 |
|
76 |
# Converta a imagem para o formato esperado pelo modelo e coloque-a na GPU
|
77 |
img = torch.FloatTensor(img).unsqueeze(0).to(device)
|
|
|
94 |
logit = logit.astype(bool)
|
95 |
|
96 |
# Crie uma cópia da imagem original para saída e aplique a máscara
|
97 |
+
img_out = ori.copy()
|
98 |
img_out[logit, 0] = 255
|
99 |
+
|
100 |
+
# Salve o resultado em um arquivo se a opção estiver ativada
|
101 |
+
if salvar_resultado:
|
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 = {
|
115 |
+
'SE-RegUNet 4GF': torch.jit.load('./model/SERegUNet4GF.pt'),
|
116 |
+
'SE-RegUNet 16GF': torch.jit.load('./model/SERegUNet16GF.pt'),
|
117 |
+
'AngioNet': torch.jit.load('./model/AngioNet.pt'),
|
118 |
+
'EffUNet++ B5': torch.jit.load('./model/EffUNetppb5.pt'),
|
119 |
+
'Reg-SA-UNet++': torch.jit.load('./model/RegSAUnetpp.pt'),
|
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 |
+
import numpy as np
|
127 |
+
import cv2
|
128 |
+
from sklearn.cluster import KMeans
|
129 |
+
|
130 |
+
def processar_imagem_de_entrada_wrapper(img, modelo, salvar_resultado=False, nome_arquivo=None):
|
131 |
+
model = models[modelo]
|
132 |
+
resultado, img_out = processar_imagem_de_entrada(img, modelo, model)
|
133 |
+
|
134 |
+
# Resto do código permanece inalterado
|
135 |
+
kmeans = KMeans(n_clusters=2, random_state=0)
|
136 |
+
flattened_img = img_out[:, :, 0].reshape((-1, 1))
|
137 |
+
kmeans.fit(flattened_img)
|
138 |
+
labels = kmeans.labels_
|
139 |
+
cluster_centers = kmeans.cluster_centers_
|
140 |
+
|
141 |
+
# Extração de características dos clusters
|
142 |
+
num_clusters = len(cluster_centers)
|
143 |
+
cluster_features = []
|
144 |
+
for i in range(num_clusters):
|
145 |
+
cluster_mask = labels == i # Create a boolean mask for the cluster
|
146 |
+
|
147 |
+
# Calcular área do cluster
|
148 |
+
area = np.sum(cluster_mask)
|
149 |
+
|
150 |
+
if area == 0: # Skip empty clusters
|
151 |
+
continue
|
152 |
+
|
153 |
+
# Calcular forma do cluster usando a relação entre área e perímetro
|
154 |
+
contours, _ = cv2.findContours(np.uint8(cluster_mask), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
155 |
+
if len(contours) > 0:
|
156 |
+
perimeter = cv2.arcLength(contours[0], True)
|
157 |
+
compactness = 4 * np.pi * area / (perimeter ** 2)
|
158 |
+
|
159 |
+
cluster_features.append({'area': area, 'compactness': compactness})
|
160 |
+
|
161 |
+
# Decidir se há doença com base nas características dos clusters
|
162 |
+
has_disease_flag = any(feature['area'] >= 200 and feature['compactness'] < 0.3 for feature in cluster_features)
|
163 |
+
|
164 |
+
# Formatar o indicador de doença como uma string
|
165 |
+
if has_disease_flag:
|
166 |
+
status_doenca = "Sim"
|
167 |
+
explanation = "A máquina detectou uma possível doença nos vasos sanguíneos."
|
168 |
+
else:
|
169 |
+
status_doenca = "Não"
|
170 |
+
explanation = "A máquina não detectou nenhuma doença nos vasos sanguíneos."
|
171 |
+
|
172 |
+
return resultado, img_out, status_doenca, explanation, f"{num_analises} análises realizadas"
|
173 |
+
|
174 |
+
|
175 |
+
# Inicializar a contagem de análises
|
176 |
+
num_analises = 0
|
177 |
+
|
178 |
+
# Criar a interface Gradio
|
179 |
+
my_app = gr.Interface(
|
180 |
+
fn=processar_imagem_de_entrada_wrapper,
|
181 |
+
inputs=[
|
182 |
+
gr.inputs.Image(label="Angiograma:", shape=(512, 512)),
|
183 |
+
gr.inputs.Dropdown(['SE-RegUNet 4GF','SE-RegUNet 16GF', 'AngioNet', 'EffUNet++ B5', 'Reg-SA-UNet++', 'UNet3+'], label='Modelo', default='SE-RegUNet 4GF'),
|
184 |
+
gr.inputs.Checkbox(label="Salvar Resultado"),
|
185 |
+
],
|
186 |
+
outputs=[
|
187 |
+
gr.outputs.Label(label="Tempo decorrido"),
|
188 |
+
gr.outputs.Image(type="numpy", label="Imagem de Saída"),
|
189 |
+
gr.outputs.Label(label="Possui Doença?"),
|
190 |
+
gr.outputs.Label(label="Explicação"),
|
191 |
+
gr.outputs.Label(label="Análises Realizadas"),
|
192 |
+
],
|
193 |
+
title="Segmentação de Angiograma Coronariano",
|
194 |
+
description="Esta aplicação segmenta angiogramas coronarianos usando modelos de segmentação pré-treinados.",
|
195 |
+
theme="default",
|
196 |
+
layout="vertical",
|
197 |
+
allow_flagging=False,
|
198 |
+
)
|
199 |
+
|
200 |
+
# Iniciar a interface Gradio
|
201 |
+
my_app.launch() otimize
|
202 |
|
203 |
+
# Criar uma pasta para salvar os resultados
|
204 |
+
if not os.path.exists(caminho_salvar_resultado):
|
205 |
+
os.makedirs(caminho_salvar_resultado)
|
206 |
|
207 |
+
# Iniciar o servidor
|
208 |
+
my_app.launch()
|