Deployed: https://floating-refuge-59093.herokuapp.com/
Look at bottom of this file for how i deployed to Heroku
Creation of IFO Dataset
Dataset Link: https://drive.google.com/file/d/1LXbEadbpuvTJVwj5thGrlMjYP9hzt6Wn/view?usp=sharing
PreProcess raw dataset: https://github.com/satyajitghana/TSAI-DeepVision-EVA4.0-Phase-2/blob/master/02-MobileNet/IFO_preprocess.ipynb
DatasetVisualization: https://github.com/satyajitghana/TSAI-DeepVision-EVA4.0-Phase-2/blob/master/02-MobileNet/01_IFODataset.ipynb
Misclassifications: https://github.com/satyajitghana/TSAI-DeepVision-EVA4.0-Phase-2/blob/master/02-MobileNet/03_Misclassifications.ipynb
class IFODataset(Dataset):
"""
Dataset generator for MobileNetV2 implementation on Identified
flying objects dataset
"""
class_names = ['Flying_Birds', 'Large_QuadCopters', 'Small_QuadCopters', 'Winged_Drones']
def __init__(self, root, source_zipfile, transform=None):
self.root = Path(root) / 'IFO'
self.root.mkdir(parents=True, exist_ok=True)
self.source_zipfile = Path(source_zipfile)
self.transform = transform
if os.path.isdir(self.root / 'IFOCleaned'):
print(f"dataset folder/files already exist in {self.root / 'IFOCleaned'}")
else:
self.extractall()
self.images_paths = sorted(list(Path(self.root / 'IFOCleaned').glob('*/*.jpg')))
self.targets = [self.class_names.index(image_path.parent.name) for image_path in self.images_paths]
print(f'found {len(self.images_paths)} images in total')
l = list(dataset.targets)
images_per_class = dict((dataset.class_names[x],l.count(x)) for x in set(l))
print(json.dumps(images_per_class, indent=4))
# split indices to train and test, use stratify to distribute equally
self.train_idxs, self.test_idxs = train_test_split(np.arange(len(self.images_paths)), test_size=0.3, shuffle=True, stratify=self.targets)
def extractall(self):
print('Extracting the dataset zip file')
zipf = ZipFile(self.source_zipfile, 'r')
zipf.extractall(self.root)
def split_dataset(self):
return Subset(self, indices=self.train_idxs), Subset(self, self.test_idxs)
def __len__(self):
return len(self.images_paths)
def __getitem__(self, index):
image_path = self.images_paths[index]
image = Image.open(image_path)
image = image.convert('RGB')
target = self.targets[index]
if self.transform:
image = self.transform(image)
return image, target
The dataset is a simple zip file with the classes in their individual folders, what’s interesting is how we transforms the images for training
Some dataset stats
{
"Flying_Birds": 8164,
"Large_QuadCopters": 4886,
"Small_QuadCopters": 3612,
"Winged_Drones": 5531
}
"mean = ['0.533459901809692', '0.584880530834198', '0.615305066108704']"
"std = ['0.172962218523026', '0.167985364794731', '0.184633478522301']"
train_transforms = A.Compose([
# A.VerticalFlip(), not useful, flying objects cannot be flipped vertically
A.HorizontalFlip(),
A.LongestMaxSize(max_size=500),
A.Normalize(mean=self.mean, std=self.std),
A.PadIfNeeded(min_height=500, min_width=500, border_mode=0, always_apply=True, value=self.mean),
A.Resize(height=224, width=224, always_apply=True),
A.Rotate(limit=30, border_mode=0, always_apply=False, value=self.mean),
A.Cutout(num_holes=2, max_h_size=48, max_w_size=48, p=0.9, fill_value=self.mean),
AT.ToTensor()
])
The Series of Transformations are
Horizontal Flip
LongestMaxSize
Normalize
PadIfNeeded
500x500
Resize
224x244
image so we convert it to suchRotate
+-30
degrees to increase the test accuracyCutOut
Dataset
Augmented Dataset
BatchLoss-Train
EpochLoss-Test
EpochLoss-Train
EpochAccuracy-Train
EpochAccuracy-Test
{
'Flying_Birds': 18,
'Large_QuadCopters': 133,
'Small_QuadCopters': 748,
'Winged_Drones': 324
}
Classification Report
precision recall f1-score support
Flying_Birds 0.96 0.99 0.98 2449
Large_QuadCopters 0.58 0.91 0.71 1466
Small_QuadCopters 0.84 0.31 0.45 1084
Winged_Drones 0.94 0.80 0.87 1659
accuracy 0.82 6658
macro avg 0.83 0.75 0.75 6658
weighted avg 0.85 0.82 0.80 6658
Flying_Birds ... Winged_Drones
Flying_Birds 2431 ... 12
Large_QuadCopters 29 ... 50
Small_QuadCopters 12 ... 24
Winged_Drones 59 ... 1335
[4 rows x 4 columns]
Confusion Matrix
Refer to ifo-app for source code
Install streamlit
pip install streamlit
Now after wrting app.py simply run streamlit run app.py
, check if everything works
Cool, Now let’s Deploy!
Make sure your requirements.txt uses these version of torch and torchvision, there are for cpu and python3.6 which heroku uses
requirements.txt
https://download.pytorch.org/whl/cpu/torch-1.6.0%2Bcpu-cp36-cp36m-linux_x86_64.whl
https://download.pytorch.org/whl/cpu/torchvision-0.7.0%2Bcpu-cp36-cp36m-linux_x86_64.whl
You can find pytorch releases here: https://download.pytorch.org/whl/torch_stable.html
now Procfile
web: sh setup.sh && streamlit run app.py
Initialize a empty git repo
git init
git add .
git commit -m "initial build"
Now create a heroku project and push to it !
heroku create
git push heroku master
NOTE: you can also connect your github repo to heroku and it’ll build on push to github