-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Changed the Waste-Segregator project file from a submodule to a folde…
…r to allow people to commit easily (#6)
- Loading branch information
1 parent
54eb3e4
commit 229d0b3
Showing
13 changed files
with
7,398 additions
and
1 deletion.
There are no files selected for viewing
Submodule Waste-Segregator_shorya
deleted from
ad55e2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
data/ | ||
faster_rcnn_implementation/resized_data/ | ||
faster_rcnn_implementation/outputs/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
|
||
# Waste Segregator | ||
|
||
### Project Description | ||
|
||
The project uses object detection to detect waste in the wild, the model uses a pretrained faster rcnn resnet50 and is trained on the [taco dataset](http://tacodataset.org/). | ||
|
||
### Prerequisites | ||
|
||
You can install the libraries needed using | ||
``` | ||
pip install -r requirements.txt | ||
``` | ||
The python version used in the project is 3.10.11 | ||
|
||
### Installation | ||
|
||
To clone the git repository use | ||
``` | ||
git clone https://github.com/Shorya1835/Waste-Segregator.git | ||
``` | ||
|
||
|
||
### Libraries Used | ||
|
||
- Pytorch | ||
- The model uses torch, torchvision for the model and torchmetrics to evaluate the model. | ||
- Numpy | ||
- For arrays | ||
- Cv2 and matplotlib | ||
- For visualization | ||
- albumentaions | ||
- For transforming the data | ||
- glob | ||
- To search for files | ||
- Chitra and ppyboxes | ||
- During data analysis for data conversion and plotting | ||
|
||
### Usage | ||
|
||
The model can detect waste in the wild and categorize it between 18 categories, which can be furhter mapped to recylable and organic, allowing effective waste segregation. The model has mAP of 6 percent, with highest 7 percent achieved. | ||
|
||
![An example](https://i.imgur.com/axekldV.png) | ||
|
||
### Structure | ||
|
||
``` | ||
Faster_rcnn_implementation | ||
├── config.py | ||
├── custom_utils.py | ||
├── datasets.py | ||
├── image_distributor.ipynb | ||
├── inference.py | ||
├── model.py | ||
├── outputs | ||
│ ├── best_model.pth | ||
│ ├── train_loss.png | ||
│ └── valid_loss.png | ||
├── resized_data | ||
│ ├── annotations.json | ||
│ ├── test | ||
│ ├── train | ||
│ └── validation | ||
└── train.py | ||
``` |
Large diffs are not rendered by default.
Oops, something went wrong.
32 changes: 32 additions & 0 deletions
32
Waste-Segregator_shorya/faster_rcnn_implementation/config.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import torch | ||
|
||
#Hyperparameters | ||
BATCH_SIZE=7 | ||
RESIZE_TO=(256,224) | ||
NUM_EPOCHS=500 | ||
NUM_WORKERS=0 | ||
|
||
#Choosing between cpu or gpu | ||
DEVICE=torch.device(('cuda') if torch.cuda.is_available() else torch.device('cpu')) | ||
|
||
#Training images | ||
TRAIN_DIR='resized_data/train' | ||
|
||
#Validation images | ||
VALID_DIR='resized_data/validation' | ||
|
||
#classes: 0 index is reserved for background | ||
CLASSES=[ | ||
'__background__','Aluminium foil', 'Bottle', 'Bottle cap', 'Broken glass', 'Can', 'Carton', 'Cup', 'Lid', 'Other plastic', 'Paper', 'Plastic bag & wrapper', 'Plastic container', 'Plastic utensils', 'Pop tab', 'Straw', 'Styrofoam piece','Cigarette','Others'] | ||
|
||
NUM_CLASSES=len(CLASSES) | ||
|
||
# whether to visualize images after crearing the data loaders | ||
VISUALIZE_TRANSFORMED_IMAGES = True | ||
|
||
# location to save model and plots | ||
OUT_DIR = 'outputs' | ||
|
||
|
||
|
||
|
144 changes: 144 additions & 0 deletions
144
Waste-Segregator_shorya/faster_rcnn_implementation/custom_utils.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import albumentations as A | ||
import cv2 | ||
import numpy as np | ||
import torch | ||
import matplotlib.pyplot as plt | ||
|
||
from albumentations.pytorch import ToTensorV2 | ||
from config import DEVICE,CLASSES | ||
|
||
plt.style.use('ggplot') | ||
|
||
|
||
class Averager: | ||
""" | ||
This class keeps track of the training and validation loss values | ||
and helps to get the average for each epoch as well. | ||
""" | ||
def __init__(self): | ||
self.current_total = 0.0 | ||
self.iterations = 0.0 | ||
|
||
def send(self, value): | ||
self.current_total += value | ||
self.iterations += 1 | ||
|
||
@property | ||
def value(self): | ||
if self.iterations == 0: | ||
return 0 | ||
else: | ||
return 1.0 * self.current_total / self.iterations | ||
|
||
def reset(self): | ||
self.current_total = 0.0 | ||
self.iterations = 0.0 | ||
|
||
class SaveBestModel: | ||
""" | ||
Class to save the best model while training. If the current epoch's | ||
validation loss is less than the previous least less, then save the | ||
model state. | ||
""" | ||
def __init__( | ||
self, best_valid_loss=float('inf') | ||
): | ||
self.best_valid_loss = best_valid_loss | ||
|
||
def __call__( | ||
self, current_valid_loss, | ||
epoch, model, optimizer | ||
): | ||
if current_valid_loss < self.best_valid_loss: | ||
self.best_valid_loss = current_valid_loss | ||
print(f"\nBest validation loss: {self.best_valid_loss}") | ||
print(f"\nSaving best model for epoch: {epoch+1}\n") | ||
torch.save({ | ||
'epoch': epoch+1, | ||
'model_state_dict': model.state_dict(), | ||
'optimizer_state_dict': optimizer.state_dict(), | ||
}, 'outputs/best_model.pth') | ||
|
||
def collate_fn(batch): | ||
""" | ||
To handle the data loading as different images may have different number | ||
of objects and to handle varying size tensors as well. | ||
""" | ||
return tuple(zip(*batch)) | ||
|
||
#Define the training tranforms | ||
def get_train_transform(): | ||
return A.Compose([ | ||
A.Flip(0.5), | ||
A.RandomRotate90(0.5), | ||
A.MotionBlur(p=0.2), | ||
A.MedianBlur(blur_limit=3, p=0.1), | ||
A.Blur(blur_limit=3, p=0.1), | ||
ToTensorV2(p=1.0), | ||
], bbox_params={ | ||
'format': 'pascal_voc', | ||
'label_fields': ['labels'] | ||
}) | ||
|
||
# define the validation transforms | ||
def get_valid_transform(): | ||
return A.Compose([ | ||
ToTensorV2(p=1.0), | ||
], bbox_params={ | ||
'format': 'pascal_voc', | ||
'label_fields': ['labels'] | ||
}) | ||
|
||
def show_tranformed_image(train_loader): | ||
""" | ||
This function shows the transformed images from the `train_loader`. | ||
Helps to check whether the tranformed images along with the corresponding | ||
labels are correct or not. | ||
Only runs if `VISUALIZE_TRANSFORMED_IMAGES = True` in config.py. | ||
""" | ||
if len(train_loader) > 0: | ||
for i in range(1): | ||
images, targets = next(iter(train_loader)) | ||
images = list(image.to(DEVICE) for image in images) | ||
targets = [{k: v.to(DEVICE) for k, v in t.items()} for t in targets] | ||
boxes = targets[i]['boxes'].cpu().numpy().astype(np.int32) | ||
labels = targets[i]['labels'].cpu().numpy().astype(np.int32) | ||
sample = images[i].permute(1, 2, 0).cpu().numpy() | ||
for box_num, box in enumerate(boxes): | ||
cv2.rectangle(sample, | ||
(box[0], box[1]), | ||
(box[2], box[3]), | ||
(0, 0, 255), 2) | ||
cv2.putText(sample, CLASSES[labels[box_num]], | ||
(box[0], box[1]-10), cv2.FONT_HERSHEY_SIMPLEX, | ||
1.0, (0, 0, 255), 2) | ||
cv2.imshow('Transformed image', sample) | ||
cv2.waitKey(0) | ||
cv2.destroyAllWindows() | ||
|
||
def save_model(epoch, model, optimizer): | ||
""" | ||
Function to save the trained model till current epoch, or whenver called | ||
""" | ||
torch.save({ | ||
'epoch': epoch+1, | ||
'model_state_dict': model.state_dict(), | ||
'optimizer_state_dict': optimizer.state_dict(), | ||
}, 'outputs/last_model.pth') | ||
|
||
|
||
def save_loss_plot(OUT_DIR, train_loss, val_loss): | ||
figure_1, train_ax = plt.subplots() | ||
figure_2, valid_ax = plt.subplots() | ||
train_ax.plot(train_loss, color='tab:blue') | ||
train_ax.set_xlabel('iterations') | ||
train_ax.set_ylabel('train loss') | ||
valid_ax.plot(val_loss, color='tab:red') | ||
valid_ax.set_xlabel('iterations') | ||
valid_ax.set_ylabel('validation loss') | ||
figure_1.savefig(f"{OUT_DIR}/train_loss.png") | ||
figure_2.savefig(f"{OUT_DIR}/valid_loss.png") | ||
print('SAVING PLOTS COMPLETE...') | ||
plt.close('all') | ||
|
||
|
Oops, something went wrong.