File size: 3,963 Bytes
050025b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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()