24D0894's picture
Enforce exact (256, 256) input size with forced resizing in app.py to prevent dimension mismatch
c3ea62f verified
Raw
History Blame Contribute Delete
3.21 kB
import gradio as gr
import torch
import torch.nn.functional as F
import nibabel as nib
import numpy as np
# Define the ConvAutoencoder model structure
class ConvAutoencoder(torch.nn.Module):
def __init__(self):
super(ConvAutoencoder, self).__init__()
# Encoder
self.encoder = torch.nn.Sequential(
torch.nn.Conv2d(1, 32, 3, stride=2, padding=1),
torch.nn.ReLU(),
torch.nn.Conv2d(32, 64, 3, stride=2, padding=1),
torch.nn.ReLU()
)
# Decoder
self.decoder = torch.nn.Sequential(
torch.nn.ConvTranspose2d(64, 32, 2, stride=2, padding=1),
torch.nn.ReLU(),
torch.nn.ConvTranspose2d(32, 1, 2, stride=2, padding=1),
torch.nn.Sigmoid()
)
def forward(self, x):
x = self.encoder(x)
x = self.decoder(x)
return x
# Load the pre-trained model
model_path = "conv_autoencoder_model.pth"
model = ConvAutoencoder()
model.load_state_dict(torch.load(model_path, map_location=torch.device("cpu")), strict=False)
model.eval()
# Prediction function
def predict(modalities):
try:
slices = []
for modality in modalities:
nii_data = nib.load(modality).get_fdata()
slices.append(nii_data)
# Average modalities to create a single-channel image
slice_avg = np.mean(slices, axis=0)
# Select the slice with maximum non-zero pixels
non_zero_counts = [np.count_nonzero(slice_avg.take(i, axis=2)) for i in range(slice_avg.shape[2])]
max_index = np.argmax(non_zero_counts)
best_slice = slice_avg.take(max_index, axis=2)
# Convert best_slice to a tensor and resize to (256, 256) using interpolation
tensor_slice = torch.tensor(best_slice).unsqueeze(0).unsqueeze(0).float() # Shape: [1, 1, H, W]
# Force resize to (256, 256)
tensor_slice_resized = F.interpolate(tensor_slice, size=(256, 256), mode="bilinear", align_corners=False)
print(f"Tensor shape after forced resize: {tensor_slice_resized.shape}") # Debugging
# Run model inference
with torch.no_grad():
reconstruction = model(tensor_slice_resized)
reconstruction_error = torch.abs(reconstruction - tensor_slice_resized).squeeze().numpy()
# Anomaly detection
error_threshold = 0.1
anomaly_detected = np.mean(reconstruction_error) > error_threshold
anomaly_message = "Anomaly Detected" if anomaly_detected else "No Anomaly Detected"
return reconstruction_error, anomaly_message
except Exception as e:
print(f"Processing error: {e}")
return np.zeros((256, 256)), f"Processing error: {e}"
# Gradio interface
iface = gr.Interface(
fn=predict,
inputs=gr.Files(type="filepath", label="Upload NIfTI Modalities (e.g., T1, T2, FLAIR)"),
outputs=[gr.Image(type="numpy", label="Reconstruction Error"), gr.Textbox(label="Anomaly Detection")],
title="Brain MRI Anomaly Detection - ConvAutoencoder",
description="Upload NIfTI files for brain anomaly detection using ConvAutoencoder.",
)
iface.launch()