Tumor-classify-system / appxxxx.py
Tudohuang's picture
Rename app.py to appxxxx.py
9ba3f40
import numpy as np
import gradio as gr
import glob
import imageio
from PIL import Image
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision.models import resnet18, ResNet18_Weights
import albumentations as A
import tqdm
import random
from sklearn.metrics import f1_score
import torchvision.models as models
import numpy as np
import torch
import torch.nn as nn
import albumentations as A
import imageio
from PIL import Image
import gradio as gr
import os
import glob
import cv2
# 創建模型
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 設置模型路徑
model_path = r"MRIy14.pt"
# 設定設備
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
class SimpleCNN(nn.Module):
def __init__(self, num_classes):
super(SimpleCNN, self).__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, padding=1)
self.relu1 = nn.ReLU()
self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, padding=1)
self.relu2 = nn.ReLU()
self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
self.conv3 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, padding=1)
self.relu3 = nn.ReLU()
self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2)
self.fc = nn.Linear(32 * 28 * 28, num_classes)
def forward(self, x):
# 保存各層輸出以供熱力圖生成
x1 = self.conv1(x)
x1_relu = self.relu1(x1)
x1_pool = self.pool1(x1_relu)
x2 = self.conv2(x1_pool)
x2_relu = self.relu2(x2)
x2_pool = self.pool2(x2_relu)
x3 = self.conv3(x2_pool)
x3_relu = self.relu3(x3)
x3_pool = self.pool3(x3_relu)
x_flatten = x3_pool.view(x3_pool.size(0), -1)
out = self.fc(x_flatten)
# 返回最終輸出和用於熱力圖的中間特徵圖 (例如 x3_relu 或 x3_pool)
return out, x3_relu # 或者 return out, x3_pool
# 創建模型
model = torch.load(model_path, map_location='cpu')
model = model.to(device)
model.eval()
transform = A.Compose([
A.Resize(224, 224),
])
'''
def predict(image, model=model, transform=transform):
#print(f"Input image path: {image}")
im = np.array(image)
im = Image.fromarray(image).convert('L')
im = np.array(im)
im = A.Resize(224, 224)(image=im)['image']
im = np.stack([im]*3, axis=0)[None, ...] #1, 3, 224, 224
im = im/np.max(im)
im_d = torch.from_numpy(im).to(device).float()
with torch.no_grad(): outputs = model(im_d)
_, predicted = torch.max(outputs, 1)
prediction = predicted.cpu().numpy()
transformed_image = transform(image=im)['image']
#transformed_image = np.transpose(transformed_image, (2, 1, 0))[None, ...]
transformed_image = np.stack([transformed_image] * 3, axis=0)[None, ...]
transformed_image = torch.from_numpy(transformed_image.astype(np.float32) / np.max(transformed_image)).to(device)
with torch.no_grad():
output = model(transformed_image.float())
prediction = torch.argmax(output, dim=1).item()
print(f"Prediction: {prediction}")
print(f"Prediction: {prediction}")
if prediction == 1:
return "Cancer"
else:
return "Healthy"
demo = gr.Interface(predict, gr.Image(), outputs=["text"])
demo.launch()
'''
import torch.nn.functional as F
def generate_heatmap(model, last_conv_layer, input_tensor, pred_class):
"""
使用 Grad-CAM 生成更精确的热力图。
"""
# 获取最后卷积层的特征图和模型输出
model.eval()
features = []
def hook_function(module, input, output):
features.append(output)
hook = last_conv_layer.register_forward_hook(hook_function)
model_output = model(input_tensor)
hook.remove()
# 获取预测类别的得分
class_score = model_output[:, pred_class]
# 计算梯度
model.zero_grad()
class_score.backward(retain_graph=True)
# 获取梯度和特征图
gradients = features[0].grad # 获取最后卷积层的梯度
pooled_gradients = torch.mean(gradients, dim=[0, 2, 3]) # 全局平均池化
# 获取特征图,并应用梯度加权
features = features[0]
for i in range(features.shape[1]):
features[:, i, :, :] *= pooled_gradients[i]
# 创建热力图
heatmap = torch.mean(features, dim=1).squeeze()
heatmap = np.maximum(heatmap.detach().cpu().numpy(), 0)
heatmap /= np.max(heatmap)
return heatmap
def overlay_heatmap(image, heatmap, intensity=0.5, threshold=0.5):
"""
优化热力图叠加逻辑。
"""
heatmap = cv2.resize(heatmap, (image.shape[1], image.shape[0]))
heatmap = np.uint8(255 * heatmap)
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
# 只在高信心区域应用热力图
mask = heatmap > np.max(heatmap) * threshold
superimposed_img = image.copy()
superimposed_img[mask] = superimposed_img[mask] * (1 - intensity) + heatmap[mask] * intensity
superimposed_img = np.clip(superimposed_img, 0, 255).astype(np.uint8)
return superimposed_img
def predict(image):
"""
預測並生成熱力圖。
"""
# 處理圖片
processed_image = transform(image=image)['image']
processed_image = np.transpose(processed_image, (2, 0, 1)).astype(np.float32)
input_tensor = torch.from_numpy(processed_image[None, ...]).to(device) # 更有效的轉換方法
# 預測
with torch.no_grad():
outputs, last_conv_output = model(input_tensor)
_, predicted = torch.max(outputs, 1)
prediction = predicted.item()
# 生成熱力圖
heatmap = generate_heatmap(last_conv_output, prediction)
result_image = overlay_heatmap(np.array(image), heatmap)
return prediction, result_image
# 使用 Gradio
demo = gr.Interface(fn=predict, inputs=gr.Image(), outputs=["text", "image"])
demo.launch()