Download src/backbone.py from 0Curious0/faster_rcnn_resnet50: direct link, hf CLI and curl.
- Browser
- Download file 3.05 kB
-
https://huggingface.co/0Curious0/faster_rcnn_resnet50/resolve/main/src/backbone.py
- Command line
-
hf download hf://0Curious0/faster_rcnn_resnet50/src/backbone.py
-
curl -L -o backbone.py https://huggingface.co/0Curious0/faster_rcnn_resnet50/resolve/main/src/backbone.py
3.05 kB
| import copy | |
| import torch | |
| import torch.nn as nn | |
| from torchvision.models import resnet50, ResNet50_Weights | |
| from torchvision import transforms | |
| from torchvision.transforms import functional as TF | |
| # creating a backbone class as we will be using different backbones in training | |
| class Backbone(nn.Module): | |
| def __init__(self, pretrained=True): | |
| # calling the super class of Backbone class | |
| super().__init__() | |
| # loading the resnet50 model with pretrained weights | |
| weights = ResNet50_Weights.DEFAULT if pretrained else None | |
| base_model = resnet50(weights=weights) | |
| # base_model.children() returns an iterator over immediate children modules, so we can convert it to a list | |
| # removing the conv5_x layer as in the paper and the last 2 avg_pool, fc layers | |
| self.backbone = nn.Sequential(*list(base_model.children())[:-3]) | |
| def forward(self, x): | |
| # passing the input through the backbone model | |
| x = self.backbone(x) | |
| return x | |
| # Here we could have used transforms.Compose(lambda img : resize_shorter_side(img), ToTensor()) without returning the target | |
| # But as a practice, we will create custom transform classes to handle both the image and its corresponding annotation dictionary. | |
| # Create a custom transform class to convert PIL images to PyTorch tensors and apply the resize transformation | |
| class ToTensorTransform: | |
| def __call__(self, img, target): | |
| img = TF.to_tensor(img) | |
| return img, target | |
| # Create a custom transform class to resize the shorter side of the image using resize_shorter_side function and update the annotation dictionary accordingly | |
| class ResizeTransform: | |
| def __init__(self, short_side=600, max_side=1000): | |
| self.short_side = short_side | |
| self.max_side = max_side | |
| def __call__(self, img, target): | |
| return self.resize_shorter_side(img, target) | |
| # resize fn to resize the shorter side of the image to a specified size while maintaining the aspect ratio, and also update the annotation dictionary with the new dimensions of the image. | |
| def resize_shorter_side(self, img, target): | |
| h, w = img.size | |
| annotation_dict = copy.deepcopy(target) | |
| scale = self.short_side / min(w, h) | |
| if scale * max(w, h) > self.max_side: | |
| scale = self.max_side / max(w, h) | |
| new_w = int(w * scale) | |
| new_h = int(h * scale) | |
| annotation_dict["size"]["new_width"] = new_w | |
| annotation_dict["size"]["new_height"] = new_h | |
| return TF.resize(img, (new_h, new_w)), annotation_dict | |
| # Create a composed transform class to apply multiple transformations sequentially | |
| class ComposedTransform: | |
| def __init__(self, transforms): | |
| self.transforms = transforms | |
| def __call__(self, img, target): | |
| for transform in self.transforms: | |
| img, target = transform(img, target) | |
| return img, target | |
| backbone_transform = ComposedTransform([ | |
| ResizeTransform(short_side=600, max_side=1000), | |
| ToTensorTransform(), | |
| ]) | |