| import pytorch_lightning as pl | |
| import torch | |
| import torch.nn as nn | |
| import utils | |
| from torchvision.models import resnet50 | |
| import torch | |
| from monai.transforms import ( | |
| Compose, Resize, ResizeWithPadOrCrop, | |
| ) | |
| from pytorch_grad_cam import GradCAM | |
| import matplotlib.colors as mcolors | |
| import matplotlib.pyplot as plt | |
| import numpy as np | |
| from PIL import Image | |
| from io import BytesIO | |
| class ResNet(pl.LightningModule): | |
| def __init__(self): | |
| super().__init__() | |
| self.save_hyperparameters() | |
| backbone = resnet50() | |
| num_input_channel = 1 | |
| layer = backbone.conv1 | |
| new_layer = nn.Conv2d( | |
| in_channels=num_input_channel, | |
| out_channels=layer.out_channels, | |
| kernel_size=layer.kernel_size, | |
| stride=layer.stride, | |
| padding=layer.padding, | |
| bias=layer.bias, | |
| ) | |
| new_layer.weight = nn.Parameter(layer.weight.sum(dim=1, keepdim=True)) | |
| backbone.conv1 = new_layer | |
| backbone.fc = nn.Sequential( | |
| nn.Linear(2048, 1024), | |
| nn.ReLU(), | |
| nn.BatchNorm1d(1024), | |
| nn.Dropout(0), | |
| nn.Linear(1024, 2), | |
| ) | |
| self.model = backbone | |
| def forward(self, x): | |
| out = self.model(x) | |
| return out | |
| val_transforms_416x628 = Compose( | |
| [ | |
| utils.CustomCLAHE(), | |
| Resize(spatial_size=628, mode="bilinear", align_corners=True, size_mode="longest"), | |
| ResizeWithPadOrCrop(spatial_size=(416, 628)), | |
| ] | |
| ) | |
| checkpoint = torch.load("classification_model.ckpt", map_location=torch.device('cpu')) | |
| model = ResNet() | |
| model.load_state_dict(checkpoint["state_dict"]) | |
| model.eval() | |
| def load_and_classify_image(image_path, device): | |
| gpu_model = model.to(device) | |
| image = val_transforms_416x628(image_path) | |
| image = image.unsqueeze(0).to(device) | |
| with torch.no_grad(): | |
| prediction = gpu_model(image) | |
| prediction = torch.nn.functional.softmax(prediction, dim=1).squeeze(0) | |
| return prediction.to('cpu'), image.to('cpu') | |
| def make_GradCAM(image, device): | |
| arr = image.numpy().squeeze() | |
| gpu_model = model.to(device) | |
| image = image.to(device) | |
| model.eval() | |
| target_layers = [gpu_model.model.layer4[-1]] | |
| cam = GradCAM(model=gpu_model, target_layers=target_layers) | |
| targets = None | |
| grayscale_cam = cam( | |
| input_tensor=image, | |
| targets=targets, | |
| aug_smooth=False, | |
| eigen_smooth=True, | |
| ) | |
| grayscale_cam = grayscale_cam.squeeze() | |
| jet = plt.colormaps.get_cmap("inferno") | |
| newcolors = jet(np.linspace(0, 1, 256)) | |
| newcolors[0, :3] = 0 | |
| new_jet = mcolors.ListedColormap(newcolors) | |
| plt.figure(figsize=(10, 10)) | |
| plt.imshow(arr, cmap='gray') | |
| plt.imshow(grayscale_cam, cmap=new_jet, alpha=0.5) | |
| plt.axis('off') | |
| buffer2 = BytesIO() | |
| plt.savefig(buffer2, format='png', bbox_inches='tight', pad_inches=0) | |
| buffer2.seek(0) | |
| gradcam_image = np.array(Image.open(buffer2)).squeeze() | |
| return gradcam_image | |