Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Tunnel dataset in pipeline #1

Merged
merged 11 commits into from
Jul 30, 2021
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,30 @@

This project has been developed during my internship at LISSI. The objective was to create a pipeline for semantic segmentation with python and pytorch.


## :warning: Prevent batch size problem for training :warning:

When you choose the batch size, you need to be careful about the value :
* `args.batch_size` != 1
* dataset size modulo `agrs.batch_size` !=1


## Path format for models saves

The train script create a new directory for each execution using the date.
* 📁 pipeline/
* 📁 save/
* 📁 model/
* 📁 yyyy-mm-dd-id/
* best_weights.pth.tar
* checkpoint.pth.tar
* learning_curves.png
* 📁 yyyy-mm-dd-id/
* ...
* 📁 model/
* 📁 yyyy-mm-dd-id/
* ...

## Pipeline architecture

* 📁 pipeline/
Expand All @@ -13,6 +37,7 @@ This project has been developed during my internship at LISSI. The objective was
* 📄 cityscapes.py
* 📄 minicity.py
* 📄 learner.py
* 📄 tunnel.py
* 📄 utils.py
* 📁 models/
* 📁 configs/
Expand All @@ -24,3 +49,4 @@ This project has been developed during my internship at LISSI. The objective was
* 📄 DenseASPP.py
* 📄 MobileNetDenseASPP.py
* 📄 UNet.py
* 📄 utils.py
15 changes: 8 additions & 7 deletions helpers/ARGS.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
# Created by Clément Malonda on 13/07/2021.

class ARGS:
def __init__(self):
self.dataset_path = "minicity"
self.batch_size = 2
def __init__(self, model, dataset_path, num_classes, batch_size=8, epochs=80):
self.dataset_path = dataset_path
self.batch_size = batch_size
self.pin_memory = True
self.num_workers = 8
self.colorjitter_factor = 0.3
Expand All @@ -16,9 +16,10 @@ def __init__(self):
self.dataset_mean = [0.485, 0.456, 0.406]
self.dataset_std = [0.229, 0.224, 0.225]
self.loss = "ce"
self.model = ""
self.copyblob = True
self.cutmix = True
self.epochs = 4
self.model = model
self.copyblob = False
self.cutmix = False
self.epochs = epochs
self.save_path = ""
self.is_pytorch_model = True
self.num_classes = 30
17 changes: 0 additions & 17 deletions learning/learner.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,23 +145,6 @@ def validate_epoch(dataloader, model, criterion, epoch, classLabels, validClasse
# Calculate IoU scores of current batch
iou.evaluateBatch(preds, labels)

# Save visualizations of first batch
if epoch_step == 0 and maskColors is not None:
for i in range(inputs.size(0)):
filename = os.path.splitext(os.path.basename(filepath[i]))[0]
# Only save inputs and labels once
if epoch == 0:
img = visim(inputs[i,:,:,:], args)
label = vislbl(labels[i,:,:], maskColors)
if len(img.shape) == 3:
cv2.imwrite(folder + '/images/{}.png'.format(filename),img[:,:,::-1])
else:
cv2.imwrite(folder + '/images/{}.png'.format(filename),img)
cv2.imwrite(folder + '/images/{}_gt.png'.format(filename),label[:,:,::-1])
# Save predictions
pred = vislbl(preds[i,:,:], maskColors)
cv2.imwrite(folder + '/images/{}_epoch_{}.png'.format(filename,epoch),pred[:,:,::-1])

# measure elapsed time
batch_time.update(time.time() - end)
end = time.time()
Expand Down
80 changes: 80 additions & 0 deletions learning/tunnel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#
# learning/tunnel.py
#
# Created by Clément Malonda on 28/07/2021.

import os
import json
import numpy as np
from PIL import Image
from PIL import ImageDraw
import matplotlib.pyplot as plt

classToVal = {"BAU": 1, "Parking" : 2, "SW": 3, "Road": 4}

class Tunnel():

voidClass = 5

id2trainid = np.array([0,1,2,3,4], dtype="uint8")

mask_colors = np.array([[0,0,0], [81,0,81], [230,150,140], [244,35,232], [128,64,128]])

validClasses = [0,1,2,3,4]

classLabels = ["Background", "BAU", "Parking", "SW", "Road"]

def __init__(self, root, split="train", transform=None, target_transform=None, transforms=None):
self.root = root
self.transform = transform
self.target_transform = target_transform
self.transforms = transforms

self.images_dir = os.path.join(self.root, "images")
self.target_dir = os.path.join(self.root, "targets")
self.split = split
self.images = list()
self.targets = dict()

assert split in ["train","val","test"], "Unknown value {} for argument split.".format(split)

for e in os.listdir(self.target_dir):
if e[-5:] == ".json":
file = open(os.path.join(self.target_dir, e))
targets_data = json.load(file)
for target_data in targets_data:
if target_data["name"] in os.listdir(self.images_dir):
self.images.append(os.path.join(self.images_dir, target_data["name"]))
poly = list()
for label in target_data["labels"]["polygonLabels"]:
x = np.array(label["allX"], dtype="int32")
y = np.array(label["allY"], dtype="int32")
points = list(zip(x, y))
poly.append((points, label["labelValue"]))
self.targets.update({os.path.join(self.images_dir, target_data["name"]) : poly})

file.close()


def __getitem__(self, index):
filepath = self.images[index]
image = Image.open(filepath).convert("RGB")
# target = np.zeros((image.size[1], image.size[0]))
target = Image.new("RGB", (image.size[0], image.size[1]))
draw = ImageDraw.Draw(target)
for e in self.targets[filepath]:
draw.polygon(e[0], fill=classToVal[e[1]])
image = np.array(image)
image = image.transpose(2, 0, 1)
target = np.array(target)[:, :, 0]
return image, target, filepath

def __len__(self):
return len(self.images)

if __name__ == "__main__":
dataset = Tunnel
t = dataset("/Users/ClementMalonda/Desktop/tunnel")
image, target, filepath = t[0]
plt.imshow(target)
plt.show()
6 changes: 3 additions & 3 deletions learning/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,13 @@ def train_trans(image, mask):
dataloaders = {}
dataloaders['train'] = torch.utils.data.DataLoader(trainset,
batch_size=args.batch_size, shuffle=True,
pin_memory=args.pin_memory, num_workers=args.num_workers)
pin_memory=args.pin_memory, num_workers=args.num_workers, drop_last=True)
dataloaders['val'] = torch.utils.data.DataLoader(valset,
batch_size=args.batch_size, shuffle=False,
pin_memory=args.pin_memory, num_workers=args.num_workers)
pin_memory=args.pin_memory, num_workers=args.num_workers, drop_last=True)
dataloaders['test'] = torch.utils.data.DataLoader(testset,
batch_size=args.batch_size, shuffle=False,
pin_memory=args.pin_memory, num_workers=args.num_workers)
pin_memory=args.pin_memory, num_workers=args.num_workers, drop_last=True)

return dataloaders

Expand Down
87 changes: 87 additions & 0 deletions models/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#
# models/utils.py
#
# Created by Clément Malonda on 30/07/2021.

import os
import time
from datetime import date

def get_model(args):
if args.model == "DeepLabV3_Resnet50":
from torchvision.models.segmentation import deeplabv3_resnet50
model = deeplabv3_resnet50(num_classes = args.num_classes)
args.is_pytorch_model = True

elif args.model == "DeepLabV3_Resnet101":
from torchvision.models.segmentation import deeplabv3_resnet101
model = deeplabv3_resnet101(num_classes = args.num_classes)
args.is_pytorch_model = True

elif args.model == "FCN_Resnet50":
from torchvision.models.segmentation import fcn_resnet50
model = fcn_resnet50(num_classes = args.num_classes)
args.is_pytorch_model = True

elif args.model == "FCN_Resnet101":
from torchvision.models.segmentation import fcn_resnet101
model = fcn_resnet101(num_classes = args.num_classes)
args.is_pytorch_model = True

elif args.model == "UNet":
from models.UNet import UNet
model = UNet(num_classes=args.num_classes)
args.is_pytorch_model = False

elif args.model == "DenseASPP121":
from models.DenseASPP import DenseASPP
from models.configs.DenseASPP121 import Model_CFG
model = DenseASPP(Model_CFG, num_classes=args.num_classes)
args.is_pytorch_model = False

elif args.model == "DenseASPP161":
from models.DenseASPP import DenseASPP
from models.configs.DenseASPP161 import Model_CFG
model = DenseASPP(Model_CFG, num_classes=args.num_classes)
args.is_pytorch_model = False

elif args.model == "DenseASPP169":
from models.DenseASPP import DenseASPP
from models.configs.DenseASPP169 import Model_CFG
model = DenseASPP(Model_CFG, num_classes=args.num_classes)
args.is_pytorch_model = False

elif args.model == "DenseASPP201":
from models.DenseASPP import DenseASPP
from models.configs.DenseASPP201 import Model_CFG
model = DenseASPP(Model_CFG, num_classes=args.num_classes)
args.is_pytorch_model = False

elif args.model == "MobileNetDenseASPP":
from models.DenseASPP import DenseASPP
from models.configs.MobileNetDenseASPP import Model_CFG
model = DenseASPP(Model_CFG, num_classes=args.num_classes)
args.is_pytorch_model = False

else:
print("Model {} is not supported".format(args.model))
print("Models can only be : \
\n\t- DeepLabV3_Resnet50 (pytorch)\
\n\t- DeepLabV3_Resnet101 (pytorch)\
\n\t- FCN_Resnet50 (pytorch)\
\n\t- FCN_Resnet101 (pytorch)\
\n\t- UNet (external)\
\n\t- DenseASPP121 (external)\
\n\t- DenseASPP161 (external)\
\n\t- DenseASPP169 (external)\
\n\t- DenseASPP201 (external)\
\n\t- MobileNetDenseASPP (external)")
exit(1)

dir = date.today().isoformat() + "-" +str(int(time.time()))
args.save_path = os.path.join("save", args.model, dir)

return model, args

def get_optimizer(args):
pass
Loading