Spaces:
Sleeping
Sleeping
| import torch | |
| import torch.nn as nn | |
| import torchvision.transforms as transforms | |
| from PIL import Image | |
| import cv2 | |
| import os | |
| # define CNN architecture | |
| class CustomCNNModel(nn.Module): | |
| def __init__(self, input_dim, num_classes): | |
| super(CustomCNNModel,self).__init__() | |
| self.input_dim = input_dim | |
| self.num_classes = num_classes | |
| self.conv_layers = nn.Sequential( | |
| nn.Conv2d(3, 32, kernel_size=3, padding =1, stride=1), | |
| nn.BatchNorm2d(32), | |
| nn.ReLU(), | |
| nn.MaxPool2d(kernel_size=2, stride=2), | |
| nn.Conv2d(32, 64, kernel_size=3, padding =1, stride=1), | |
| nn.BatchNorm2d(64), | |
| nn.ReLU(), | |
| nn.MaxPool2d(kernel_size=2, stride=2), | |
| nn.Conv2d(64, 128, kernel_size=3, padding =1, stride=1), | |
| nn.BatchNorm2d(128), | |
| nn.ReLU(), | |
| nn.MaxPool2d(kernel_size=2, stride=2), | |
| nn.Conv2d(128, 256, kernel_size=3, padding =1, stride=1), | |
| nn.BatchNorm2d(256), | |
| nn.ReLU(), | |
| nn.MaxPool2d(kernel_size=2, stride=2), | |
| ) | |
| self._to_linear = None | |
| self._get_conv_output(self.input_dim) | |
| self.fc_layers = nn.Sequential( | |
| nn.Linear(self._to_linear, 512), | |
| nn.ReLU(), | |
| nn.Linear(512, 128), | |
| nn.ReLU(), | |
| nn.Linear(128,self.num_classes) | |
| ) | |
| def forward(self, x): | |
| x = self.conv_layers(x) | |
| x = x.view(x.size(0),-1) | |
| x = self.fc_layers(x) | |
| return x | |
| def _get_conv_output(self, input_dim=128): | |
| with torch.no_grad(): | |
| dummy_input = torch.zeros(1, 3,input_dim, input_dim) #batch size, no of channels, input | |
| output = self.conv_layers(dummy_input) | |
| self._to_linear = output.view(1, -1).size(1) | |
| # load CNN architecture trained weights | |
| # index to label map | |
| # transformation | |
| class ImageClassifier(): | |
| def __init__(self, model_path, class_names=None): | |
| self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') | |
| self.model = CustomCNNModel(input_dim=128, num_classes=3).to(self.device) | |
| self.model.load_state_dict(torch.load(model_path, map_location = self.device)) | |
| self.model.eval() | |
| if class_names is None: | |
| self.class_names = {0: 'person', 1: 'Dog', 2: 'Cat'} | |
| else: | |
| self.class_names = class_names | |
| self.transform = transforms.Compose([ | |
| transforms.Resize((128, 128)), | |
| transforms.ToTensor(), | |
| transforms.Normalize(mean=[0.5, 0.5, 0.5], std = [0.5, 0.5, 0.5]) | |
| ]) | |
| # load image with pillow(pytorch expects pillow) | |
| # prediction | |
| # label map --> class | |
| # opencv, write text on our input image | |
| # return class, output image | |
| def predict(self, image_path): | |
| image = Image.open(image_path).convert("RGB") | |
| image_tensor = self.transform(image).unsqueeze(0).to(self.device) # adds batch size to the image unsqueeze | |
| with torch.no_grad(): | |
| output = self.model(image_tensor) | |
| ## [[0.3, 0.7, 0.9]] -> 2D tensor | |
| _, predicted = torch.max(output, 1) | |
| label = self.class_names[predicted.item()] | |
| img = cv2.imread(image_path) | |
| cv2.putText(img, label, (10,30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2) | |
| output_path = "output_image.jpg" | |
| cv2.imwrite("output_image.jpg",img) | |
| cwd = os.getcwd() | |
| output_path = os.path.join(cwd, output_path) | |
| return label, output_path | |
| ## CNN Architecture | |
| ## CNN() model instance | |
| ## CNN.load_dict() | |