da_detection / src /main.py
davidwardan's picture
main corrected
042d947 verified
Raw
History Blame Contribute Delete
4.25 kB
import torch
import torch.nn as nn
from torchvision import transforms, models
from torchvision.transforms import InterpolationMode
from torch.utils.data import Dataset, DataLoader
import gradio as gr
from src.utils import utils
from PIL import Image
import numpy as np
def main(window_size: int = 224):
# Set the device
np.random.seed(0)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print("Running on {}".format(device))
def predict(inp, stride_size, threshold):
# Apply sliding window on the image
windows, pad_size = utils.sliding_window(
inp, (window_size, window_size), (stride_size, stride_size)
)
# Define the transformations to be applied to the images
transform = transforms.Compose(
[
transforms.Resize([256], interpolation=InterpolationMode.BICUBIC),
transforms.CenterCrop([224]),
transforms.ToTensor(), # Converts the image to [0.0, 1.0] range
transforms.Normalize(
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]
),
]
)
# Custom dataset class
class CustomDataset(Dataset):
def __init__(self, data, transform=None):
self.data = data
self.transform = transform
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
image, position = self.data[idx]
if self.transform:
image = self.transform(image)
return image, position
# Create custom datasets with transformations
dataset = CustomDataset(windows, transform=transform)
dataloader = DataLoader(dataset, batch_size=128, shuffle=False)
# Load a pretrained ResNet model
model = models.resnet50().to(device)
# Modify the output layer directly to match binary classification
model.fc = nn.Sequential(
nn.Linear(model.fc.in_features, 128),
nn.ReLU(inplace=True),
nn.Linear(128, 1),
).to(device)
# load model weights (Ensure map_location points to the correct device)
model.load_state_dict(
torch.load("./weights/resnet.pth", map_location=device, weights_only=True)
)
model = model.to(device)
model.eval()
heatmap = []
for data in dataloader:
images, positions = data
images = images.to(device)
with torch.no_grad():
outputs = model(images)
for i in range(len(outputs)):
probability = torch.sigmoid(outputs[i]).item()
img = Image.new(
"RGB",
(window_size, window_size),
color=(int(255 * probability), 0, 0),
)
heatmap.append((img, (positions[0][i], positions[1][i])))
# overlay the heatmap on the original image
result, _ = utils.reconstruct_image(
heatmap, pad_size, (window_size, window_size)
)
prob_threshold = round(threshold * 255, 0)
result = result.point(
lambda p: p * 0 if p < prob_threshold else p
) # set any pixel value less than
# threshold to 0
reconstructed_image, _ = utils.reconstruct_image(
windows, pad_size, (window_size, window_size)
)
result = Image.blend(reconstructed_image, result, alpha=0.5)
# slice the image to remove the padding
# result = result.crop((0, 0, inp.width, inp.height))
return result
# Gradio Interface with stride size input slider
demo = gr.Interface(
fn=predict,
inputs=[
gr.Image(type="pil"),
gr.Slider(minimum=32, maximum=224, step=32, label="Stride Size"),
gr.Slider(minimum=0.5, maximum=1.0, step=0.1, label="Threshold"),
],
outputs=gr.Image(type="pil"),
)
# launch the interface in a new tab
demo.launch(inbrowser=True, share=True, debug=True)
if __name__ == "__main__":
main()