376 KiB
376 KiB
import os
if not os.path.exists('open-images-bus-trucks'):
!pip install -q torch_snippets
!wget --quiet https://www.dropbox.com/s/agmzwk95v96ihic/open-images-bus-trucks.tar.xz
!tar -xf open-images-bus-trucks.tar.xz
!rm open-images-bus-trucks.tar.xz
!git clone https://github.com/sizhky/ssd-utils/
%cd ssd-utils
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts. spyder 5.1.5 requires pyqtwebengine<5.13, which is not installed. spyder 5.1.5 requires pyqt5<5.13, but you have pyqt5 5.15.9 which is incompatible. pylint 2.7.2 requires astroid<2.6,>=2.5.1, but you have astroid 2.5 which is incompatible. 'wget' is not recognized as an internal or external command, operable program or batch file. tar: Error opening archive: Failed to open 'open-images-bus-trucks.tar.xz' 'rm' is not recognized as an internal or external command, operable program or batch file.
f:\Zajecia\books\computer_vision\Modern-Computer-Vision-with-PyTorch-master\Modern-Computer-Vision-with-PyTorch-master\Modern-Computer-Vision-with-PyTorch-master\Chapter08\ssd-utils
Cloning into 'ssd-utils'...
from torch_snippets import *
DATA_ROOT = '../open-images-bus-trucks/'
IMAGE_ROOT = f'{DATA_ROOT}/images'
DF_RAW = df = pd.read_csv(f'{DATA_ROOT}/df.csv')
df = df[df['ImageID'].isin(df['ImageID'].unique().tolist())]
label2target = {l:t+1 for t,l in enumerate(DF_RAW['LabelName'].unique())}
label2target['background'] = 0
target2label = {t:l for l,t in label2target.items()}
background_class = label2target['background']
num_classes = len(label2target)
device = 'cuda' if torch.cuda.is_available() else 'cpu'
import collections, os, torch
from PIL import Image
from torchvision import transforms
normalize = transforms.Normalize(
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]
)
denormalize = transforms.Normalize(
mean=[-0.485/0.229, -0.456/0.224, -0.406/0.255],
std=[1/0.229, 1/0.224, 1/0.255]
)
def preprocess_image(img):
img = torch.tensor(img).permute(2,0,1)
img = normalize(img)
return img.to(device).float()
class OpenDataset(torch.utils.data.Dataset):
w, h = 300, 300
def __init__(self, df, image_dir=IMAGE_ROOT):
self.image_dir = image_dir
self.files = glob.glob(self.image_dir+'/*')
self.df = df
self.image_infos = df.ImageID.unique()
logger.info(f'{len(self)} items loaded')
def __getitem__(self, ix):
# load images and masks
image_id = self.image_infos[ix]
img_path = find(image_id, self.files)
img = Image.open(img_path).convert("RGB")
img = np.array(img.resize((self.w, self.h), resample=Image.BILINEAR))/255.
data = df[df['ImageID'] == image_id]
labels = data['LabelName'].values.tolist()
data = data[['XMin','YMin','XMax','YMax']].values
data[:,[0,2]] *= self.w
data[:,[1,3]] *= self.h
boxes = data.astype(np.uint32).tolist() # convert to absolute coordinates
return img, boxes, labels
def collate_fn(self, batch):
images, boxes, labels = [], [], []
for item in batch:
img, image_boxes, image_labels = item
img = preprocess_image(img)[None]
images.append(img)
boxes.append(torch.tensor(image_boxes).float().to(device)/300.)
labels.append(torch.tensor([label2target[c] for c in image_labels]).long().to(device))
images = torch.cat(images).to(device)
return images, boxes, labels
def __len__(self):
return len(self.image_infos)
from sklearn.model_selection import train_test_split
trn_ids, val_ids = train_test_split(df.ImageID.unique(), test_size=0.1, random_state=99)
trn_df, val_df = df[df['ImageID'].isin(trn_ids)], df[df['ImageID'].isin(val_ids)]
len(trn_df), len(val_df)
train_ds = OpenDataset(trn_df)
test_ds = OpenDataset(val_df)
train_loader = DataLoader(train_ds, batch_size=4, collate_fn=train_ds.collate_fn, drop_last=True)
test_loader = DataLoader(test_ds, batch_size=4, collate_fn=test_ds.collate_fn, drop_last=True)
2020-10-13 10:38:19.093 | INFO | __main__:__init__:25 - 13702 items loaded 2020-10-13 10:38:19.138 | INFO | __main__:__init__:25 - 1523 items loaded
def train_batch(inputs, model, criterion, optimizer):
model.train()
N = len(train_loader)
images, boxes, labels = inputs
_regr, _clss = model(images)
loss = criterion(_regr, _clss, boxes, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
return loss
@torch.no_grad()
def validate_batch(inputs, model, criterion):
model.eval()
images, boxes, labels = inputs
_regr, _clss = model(images)
loss = criterion(_regr, _clss, boxes, labels)
return loss
from model import SSD300, MultiBoxLoss
from detect import *
n_epochs = 3
model = SSD300(num_classes, device)
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4, weight_decay=1e-5)
criterion = MultiBoxLoss(priors_cxcy=model.priors_cxcy, device=device)
log = Report(n_epochs=n_epochs)
logs_to_print = 5
Downloading: "https://download.pytorch.org/models/vgg16-397923af.pth" to /root/.cache/torch/hub/checkpoints/vgg16-397923af.pth
HBox(children=(FloatProgress(value=0.0, max=553433881.0), HTML(value='')))
Loaded base model.
/usr/local/lib/python3.6/dist-packages/torch/nn/_reduction.py:44: UserWarning: size_average and reduce args will be deprecated, please use reduction='none' instead. warnings.warn(warning.format(ret))
for epoch in range(n_epochs):
_n = len(train_loader)
for ix, inputs in enumerate(train_loader):
loss = train_batch(inputs, model, criterion, optimizer)
pos = (epoch + (ix+1)/_n)
log.record(pos, trn_loss=loss.item(), end='\r')
_n = len(test_loader)
for ix,inputs in enumerate(test_loader):
loss = validate_batch(inputs, model, criterion)
pos = (epoch + (ix+1)/_n)
log.record(pos, val_loss=loss.item(), end='\r')
image_paths = Glob(f'{DATA_ROOT}/images/*')
image_id = choose(test_ds.image_infos)
img_path = find(image_id, test_ds.files)
original_image = Image.open(img_path, mode='r')
original_image = original_image.convert('RGB')
2020-10-13 10:39:28.949 | INFO | torch_snippets.loader:Glob:178 - 15225 files found at ../open-images-bus-trucks//images/*
image_paths = Glob(f'{DATA_ROOT}/images/*')
for _ in range(3):
image_id = choose(test_ds.image_infos)
img_path = find(image_id, test_ds.files)
original_image = Image.open(img_path, mode='r')
bbs, labels, scores = detect(original_image, model, min_score=0.9, max_overlap=0.5,top_k=200, device=device)
labels = [target2label[c.item()] for c in labels]
label_with_conf = [f'{l} @ {s:.2f}' for l,s in zip(labels,scores)]
print(bbs, label_with_conf)
show(original_image, bbs=bbs, texts=label_with_conf, text_sz=10)
[[35, 34, 212, 123]] ['Truck @ 1.00']
[[6, 1, 250, 215]] ['Bus @ 1.00']
[[58, 22, 194, 170]] ['Bus @ 1.00']