spuuntries commited on
Commit
8f7598e
1 Parent(s): b35ea03

feat: add project files

Browse files
Files changed (5) hide show
  1. .gitignore +1 -0
  2. app.py +112 -0
  3. bjf8fp.safetensors +3 -0
  4. models.py +141 -0
  5. requirements.txt +5 -0
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ __pycache__/
app.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ from PIL import Image
4
+ import torchvision.transforms as transforms
5
+ import numpy as np
6
+ from safetensors.torch import load_model, save_model
7
+ from models import *
8
+ import os
9
+
10
+
11
+ class WasteClassifier:
12
+ def __init__(self, model, class_names, device):
13
+ self.model = model
14
+ self.class_names = class_names
15
+ self.device = device
16
+ self.transform = transforms.Compose(
17
+ [
18
+ transforms.Resize((384, 384)),
19
+ transforms.ToTensor(),
20
+ transforms.Normalize(
21
+ mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]
22
+ ),
23
+ ]
24
+ )
25
+
26
+ def predict(self, image):
27
+ self.model.eval()
28
+
29
+ if not isinstance(image, Image.Image):
30
+ image = Image.fromarray(image)
31
+
32
+ original_size = image.size
33
+ img_tensor = self.transform(image).unsqueeze(0).to(self.device)
34
+
35
+ with torch.no_grad():
36
+ outputs = self.model(img_tensor)
37
+ probabilities = torch.nn.functional.softmax(outputs, dim=1)
38
+
39
+ probs = probabilities[0].cpu().numpy()
40
+ pred_class = self.class_names[np.argmax(probs)]
41
+ confidence = np.max(probs)
42
+
43
+ results = {
44
+ "predicted_class": pred_class,
45
+ "confidence": confidence,
46
+ "class_probabilities": {
47
+ class_name: float(prob)
48
+ for class_name, prob in zip(self.class_names, probs)
49
+ },
50
+ }
51
+
52
+ return results
53
+
54
+
55
+ def interface(classifier):
56
+ def process_image(image):
57
+ results = classifier.predict(image)
58
+
59
+ output_str = f"Predicted Class: {results['predicted_class']}\n"
60
+ output_str += f"Confidence: {results['confidence']*100:.2f}%\n\n"
61
+ output_str += "Class Probabilities:\n"
62
+
63
+ sorted_probs = sorted(
64
+ results["class_probabilities"].items(), key=lambda x: x[1], reverse=True
65
+ )
66
+
67
+ for class_name, prob in sorted_probs:
68
+ output_str += f"{class_name}: {prob*100:.2f}%\n"
69
+
70
+ return output_str
71
+
72
+ demo = gr.Interface(
73
+ fn=process_image,
74
+ inputs=[gr.Image(type="pil", label="Upload Image")],
75
+ outputs=[gr.Textbox(label="Classification Results")],
76
+ title="Waste Classification System",
77
+ description="""
78
+ Upload an image of waste to classify it into different categories.
79
+ The model will predict the type of waste and show confidence scores for each category.
80
+ """,
81
+ examples=(
82
+ [["example1.jpg"], ["example2.jpg"], ["example3.jpg"]]
83
+ if os.path.exists("example1.jpg")
84
+ else None
85
+ ),
86
+ analytics_enabled=False,
87
+ theme="default",
88
+ )
89
+
90
+ return demo
91
+
92
+
93
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
94
+ class_names = [
95
+ "Cardboard",
96
+ "Food Organics",
97
+ "Glass",
98
+ "Metal",
99
+ "Miscellaneous Trash",
100
+ "Paper",
101
+ "Plastic",
102
+ "Textile Trash",
103
+ "Vegetation",
104
+ ]
105
+ best_model = ResNet50(num_classes=len(class_names))
106
+ best_model = best_model.to(device)
107
+ load_model(best_model, os.path.join(__file__, "..", "bjf8fp.safetensors"))
108
+
109
+ classifier = WasteClassifier(best_model, class_names, device)
110
+
111
+ demo = interface(classifier)
112
+ demo.launch(share=True)
bjf8fp.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:94e364935fe6427d14f6c9aaaa179ab707d33b27d1a3cf4705e6033595e562ea
3
+ size 94347292
models.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+
4
+
5
+ class BasicBlock(nn.Module):
6
+ expansion = 1
7
+
8
+ def __init__(self, in_planes, planes, stride=1):
9
+ super(BasicBlock, self).__init__()
10
+ self.conv1 = nn.Conv2d(
11
+ in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False
12
+ )
13
+ self.bn1 = nn.BatchNorm2d(planes)
14
+ self.conv2 = nn.Conv2d(
15
+ planes, planes, kernel_size=3, stride=1, padding=1, bias=False
16
+ )
17
+ self.bn2 = nn.BatchNorm2d(planes)
18
+
19
+ self.shortcut = nn.Sequential()
20
+ if stride != 1 or in_planes != self.expansion * planes:
21
+ self.shortcut = nn.Sequential(
22
+ nn.Conv2d(
23
+ in_planes,
24
+ self.expansion * planes,
25
+ kernel_size=1,
26
+ stride=stride,
27
+ bias=False,
28
+ ),
29
+ nn.BatchNorm2d(self.expansion * planes),
30
+ )
31
+
32
+ def forward(self, x):
33
+ out = torch.relu(self.bn1(self.conv1(x)))
34
+ out = self.bn2(self.conv2(out))
35
+ out += self.shortcut(x)
36
+ out = torch.relu(out)
37
+ return out
38
+
39
+
40
+ class Bottleneck(nn.Module):
41
+ expansion = 4
42
+
43
+ def __init__(self, in_planes, planes, stride=1):
44
+ super(Bottleneck, self).__init__()
45
+ self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)
46
+ self.bn1 = nn.BatchNorm2d(planes)
47
+ self.conv2 = nn.Conv2d(
48
+ planes, planes, kernel_size=3, stride=stride, padding=1, bias=False
49
+ )
50
+ self.bn2 = nn.BatchNorm2d(planes)
51
+ self.conv3 = nn.Conv2d(
52
+ planes, self.expansion * planes, kernel_size=1, bias=False
53
+ )
54
+ self.bn3 = nn.BatchNorm2d(self.expansion * planes)
55
+
56
+ self.shortcut = nn.Sequential()
57
+ if stride != 1 or in_planes != self.expansion * planes:
58
+ self.shortcut = nn.Sequential(
59
+ nn.Conv2d(
60
+ in_planes,
61
+ self.expansion * planes,
62
+ kernel_size=1,
63
+ stride=stride,
64
+ bias=False,
65
+ ),
66
+ nn.BatchNorm2d(self.expansion * planes),
67
+ )
68
+
69
+ def forward(self, x):
70
+ out = torch.relu(self.bn1(self.conv1(x)))
71
+ out = torch.relu(self.bn2(self.conv2(out)))
72
+ out = self.bn3(self.conv3(out))
73
+ out += self.shortcut(x)
74
+ out = torch.relu(out)
75
+ return out
76
+
77
+
78
+ class ResNet(nn.Module):
79
+ def __init__(self, block, num_blocks, num_classes=1000, K=10, T=0.5):
80
+ super(ResNet, self).__init__()
81
+ self.in_planes = 64
82
+ self.K = K
83
+ self.T = T
84
+
85
+ self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
86
+ self.bn1 = nn.BatchNorm2d(64)
87
+ self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
88
+ self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
89
+ self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
90
+ self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
91
+ self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
92
+ self.fc = nn.Linear(512 * block.expansion, num_classes)
93
+
94
+ def _make_layer(self, block, planes, num_blocks, stride):
95
+ strides = [stride] + [1] * (num_blocks - 1)
96
+ layers = []
97
+ for stride in strides:
98
+ layers.append(block(self.in_planes, planes, stride))
99
+ self.in_planes = planes * block.expansion
100
+ return nn.Sequential(*layers)
101
+
102
+ def t_max_avg_pooling(self, x):
103
+ B, C, H, W = x.shape
104
+ x_flat = x.view(B, C, -1)
105
+ top_k_values, _ = torch.topk(x_flat, self.K, dim=2)
106
+ max_values = top_k_values.max(dim=2)[0]
107
+ avg_values = top_k_values.mean(dim=2)
108
+ output = torch.where(max_values >= self.T, max_values, avg_values)
109
+ return output
110
+
111
+ def forward(self, x):
112
+ out = torch.relu(self.bn1(self.conv1(x)))
113
+ out = self.maxpool(out)
114
+ out = self.layer1(out)
115
+ out = self.layer2(out)
116
+ out = self.layer3(out)
117
+ out = self.layer4(out)
118
+ out = self.t_max_avg_pooling(out)
119
+ out = out.view(out.size(0), -1)
120
+ out = self.fc(out)
121
+ return out
122
+
123
+
124
+ def ResNet18(num_classes=1000, K=10, T=0.5):
125
+ return ResNet(BasicBlock, [2, 2, 2, 2], num_classes, K, T)
126
+
127
+
128
+ def ResNet34(num_classes=1000, K=10, T=0.5):
129
+ return ResNet(BasicBlock, [3, 4, 6, 3], num_classes, K, T)
130
+
131
+
132
+ def ResNet50(num_classes=1000, K=10, T=0.5):
133
+ return ResNet(Bottleneck, [3, 4, 6, 3], num_classes, K, T)
134
+
135
+
136
+ def ResNet101(num_classes=1000, K=10, T=0.5):
137
+ return ResNet(Bottleneck, [3, 4, 23, 3], num_classes, K, T)
138
+
139
+
140
+ def ResNet152(num_classes=1000, K=10, T=0.5):
141
+ return ResNet(Bottleneck, [3, 8, 36, 3], num_classes, K, T)
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ torch
2
+ torchvision
3
+ pillow
4
+ gradio
5
+ numpy