Adding first working tracking notebook

This commit is contained in:
Casey Hong 2020-06-15 17:43:13 -04:00 коммит произвёл GitHub
Родитель 8577f3a7ea
Коммит 54f637101d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 653 добавлений и 228 удалений

Просмотреть файл

@ -0,0 +1,276 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<i>Copyright (c) Microsoft Corporation. All rights reserved.</i>\n",
"\n",
"<i>Licensed under the MIT License.</i>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Training a Multi-Object Tracking Model"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Initialization"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"TorchVision: 0.4.0a0\n",
"Torch is using GPU: Tesla K80\n"
]
}
],
"source": [
"import sys\n",
"\n",
"sys.path.append(\"../../\")\n",
"\n",
"import os\n",
"import time\n",
"import matplotlib.pyplot as plt\n",
"from typing import Iterator\n",
"from pathlib import Path\n",
"from PIL import Image\n",
"from random import randrange\n",
"from typing import Tuple\n",
"import torch\n",
"import torchvision\n",
"from torchvision import transforms\n",
"import scrapbook as sb\n",
"\n",
"from ipywidgets import Video\n",
"from utils_cv.tracking.dataset import TrackingDataset\n",
"from utils_cv.tracking.model import TrackingLearner\n",
"\n",
"from utils_cv.common.gpu import which_processor, is_windows\n",
"\n",
"# Change matplotlib backend so that plots are shown for windows\n",
"if is_windows():\n",
" plt.switch_backend(\"TkAgg\")\n",
"\n",
"print(f\"TorchVision: {torchvision.__version__}\")\n",
"which_processor()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This shows your machine's GPUs (if it has any) and the computing device `torch/torchvision` is using."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# Ensure edits to libraries are loaded and plotting is shown in the notebook.\n",
"%reload_ext autoreload\n",
"%autoreload 2\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, set some model runtime parameters."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"tags": [
"parameters"
]
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Using torch device: cuda\n"
]
}
],
"source": [
"EPOCHS = 2\n",
"LEARNING_RATE = 0.0001\n",
"BATCH_SIZE = 1\n",
"SAVE_MODEL = True\n",
"\n",
"# train on the GPU or on the CPU, if a GPU is not available\n",
"device = torch.device(\"cuda\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
"print(f\"Using torch device: {device}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Prepare Training Dataset"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['labels_with_ids', '.ipynb_checkpoints', 'images']"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"DATA_PATH_TRAIN = \"./data/odFridgeObjects_FairMOTformat/\"\n",
"os.listdir(DATA_PATH_TRAIN)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Load Training Dataset"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"================================================================================\n",
"dataset summary\n",
"OrderedDict([('default', 4.0)])\n",
"total # identities: 5\n",
"start index\n",
"OrderedDict([('default', 0)])\n",
"================================================================================\n"
]
}
],
"source": [
"data_train = TrackingDataset(\n",
" DATA_PATH_TRAIN,\n",
" batch_size=BATCH_SIZE\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Finetune a Pretrained Model"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: <class 'utils_cv.tracking.references.fairmot.models.networks.pose_dla_dcn.DLASeg'>\n"
]
}
],
"source": [
"tracker = TrackingLearner(data_train) \n",
"print(f\"Model: {type(tracker.model)}\")"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/anaconda/envs/cv/lib/python3.7/site-packages/torch/nn/_reduction.py:43: UserWarning: size_average and reduce args will be deprecated, please use reduction='sum' instead.\n",
" warnings.warn(warning.format(ret))\n"
]
}
],
"source": [
"tracker.fit(num_epochs=EPOCHS, lr=LEARNING_RATE)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "cv",
"language": "python",
"name": "cv"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {
"height": "calc(100% - 180px)",
"left": "10px",
"top": "150px",
"width": "356.263px"
},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 2
}

Просмотреть файл

@ -0,0 +1,5 @@
# Multi-Object Tracking
```diff
+ June 2020: This work is ongoing.
```

Просмотреть файл

@ -77,3 +77,4 @@ def system_info():
print(f"{i}: {cuda.get_device_name(i)}")
else:
print("CPUs only, no GPUs found")

Просмотреть файл

@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from utils_cv.detection.bbox import _Bbox

Просмотреть файл

@ -1,10 +1,13 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import os
import os.path as osp
from typing import Dict
from torch.utils.data import DataLoader
from torchvision.transforms import transforms as T
from .references.fairmot.datasets.dataset.jde import JointDataset
from .opts import opts
from ..common.gpu import db_num_workers
@ -12,28 +15,32 @@ class TrackingDataset:
"""A multi-object tracking dataset."""
def __init__(
self, data_root: str, train_paths: Dict, batch_size: int = 12
self,
data_root: str,
name: str = "default",
batch_size: int = 12,
) -> None:
"""
Args:
data_root: root data directory
train_paths: dictionary of paths defining training data
data_root: root data directory containing image and annotation subdirectories
name: user-friendly name for the dataset
batch_size: batch size
Note: the path dictionaries map user-friendly dataset name to a filename, e.g. {"custom": "MyCustomDataset.train"}
The file is a raw text file listing the sequence of image paths. Multiple sequences (videos) can be listed,
and the sequences must be in order.
TODO: train-test split
"""
transforms = T.Compose([T.ToTensor()])
self.batch_size = batch_size
opt = opts()
train_list_path = osp.join(data_root, "{}.train".format(name))
with open(train_list_path, "a") as f:
for im_name in sorted(os.listdir(osp.join(data_root, "images"))):
f.write(osp.join("images", im_name) + "\n")
self.train_data = JointDataset(
opt,
opt.opt,
data_root,
train_paths,
im_size,
{name: train_list_path},
(opt.input_w, opt.input_h),
augment=True,
transforms=transforms,
)
@ -49,4 +56,4 @@ class TrackingDataset:
num_workers=db_num_workers(),
pin_memory=True,
drop_last=True,
)
)

Просмотреть файл

@ -4,11 +4,14 @@
import argparse
import os
import os.path as osp
from typing import List, Dict
from typing import Dict, List
import requests
import torch
import torch.cuda as cuda
import torch.nn as nn
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
from .references.fairmot.datasets.dataset.jde import LoadImages, LoadVideo
from .references.fairmot.models.model import (
@ -16,11 +19,12 @@ from .references.fairmot.models.model import (
load_model,
)
from .references.fairmot.tracker.multitracker import JDETracker
from .references.fairmot.trains.train_factory import train_factory
from .bbox import TrackingBbox
from .dataset import TrackingDataset
from .opts import opts
from ..common.gpu import torch_device
from ..common.gpu import torch_device, get_gpu_str
BASELINE_URL = (
"https://drive.google.com/open?id=1udpOPum8fJdoEQm6n0jsIgMMViOMFinu"
@ -64,6 +68,12 @@ def _download_baseline(url, destination) -> None:
save_response_content(response, destination)
def _get_gpu_str():
if cuda.is_available():
devices = [str(x) for x in range(cuda.device_count())]
return ",".join(devices)
else:
return "-1" # cpu
class TrackingLearner(object):
"""Tracking Learner for Multi-Object Tracking"""
@ -88,15 +98,14 @@ class TrackingLearner(object):
head_conv: conv layer channels for output head. None maps to the default setting.
Set 0 for no conv layer, 256 for resnets, and 256 for dla
"""
self.opt = opts().opt
self.opt = opts()
self.opt.arch = arch
self.opt.head_conv = head_conv if head_conv else -1
self.opt.gpus = get_gpu_str()
self.opt.device = torch_device()
self.dataset = dataset
self.model = model if model is not None else self.init_model()
self.device = torch_device()
# TODO setup logging
def init_model(self) -> nn.Module:
"""
@ -107,7 +116,7 @@ class TrackingLearner(object):
_download_baseline(BASELINE_URL, osp.join(model_dir, "all_dla34.pth"))
return create_model(self.opt.arch, self.opt.heads, self.opt.head_conv)
def load(self, path: str = None, resume = False) -> None:
def load(self, path: str = None, resume=False) -> None:
"""
Load a model from path.
"""
@ -132,12 +141,7 @@ class TrackingLearner(object):
self.model = load_model(self.model, path)
def fit(
self,
lr: float = 1e-4,
lr_step: str = "20,27",
num_epochs: int = 30,
num_iters: int = None,
val_intervals: int = 5,
self, lr: float = 1e-4, lr_step: str = "20,27", num_epochs: int = 30,
) -> None:
"""
The main training loop.
@ -146,8 +150,6 @@ class TrackingLearner(object):
lr: learning rate for batch size 32
lr_step: when to drop learning rate by 10
num_epochs: total training epochs
num_iters: Defaults to #samples / batch_size
val_intervals: number of epochs to run validation
Raise:
Exception if dataset is undefined
@ -160,9 +162,6 @@ class TrackingLearner(object):
self.opt.lr = lr
self.opt.lr_step = lr_step
self.opt.num_epochs = num_epochs
self.opt.num_iters = num_iters if num_iters else -1
self.opt.val_intervals = val_intervals
self.opt.device = self.device
# update dataset options
self.opt.update_dataset_info_and_set_heads(self.dataset.train_data)
@ -170,11 +169,11 @@ class TrackingLearner(object):
# initialize dataloader
train_loader = self.dataset.train_dl
self.optimizer = torch.optim.Adam(model.parameters(), self.opt.lr)
self.optimizer = torch.optim.Adam(self.model.parameters(), self.opt.lr)
self.start_epoch = 0
Trainer = train_factory[self.opt.task]
trainer = Trainer(self.opt, self.model, self.optimizer)
trainer = Trainer(self.opt.opt, self.model, self.optimizer)
trainer.set_device(
self.opt.gpus, self.opt.chunk_sizes, self.opt.device
)
@ -183,10 +182,8 @@ class TrackingLearner(object):
for epoch in range(self.start_epoch + 1, self.opt.num_epochs + 1):
mark = epoch if self.opt.save_all else "last"
log_dict_train, _ = trainer.train(epoch, train_loader)
## TODO logging
if epoch in self.opt.lr_step:
lr = self.opt.lr * (0.1 ** self.opt.lr_step.index(epoch) + 1)
## TODO logging
lr = self.opt.lr * (0.1 ** (self.opt.lr_step.index(epoch) + 1))
for param_group in optimizer.param_groups:
param_group["lr"] = lr
@ -230,10 +227,9 @@ class TrackingLearner(object):
input_height = input_h if input_h else -1
input_width = input_w if input_w else -1
self.opt.update_dataset_res(input_height, input_width)
self.opt.device = self.device
# initialize tracker
tracker = JDETracker(self.opt, frame_rate=frame_rate)
tracker = JDETracker(self.opt.opt, frame_rate=frame_rate)
# initialize dataloader
dataloader = self.get_dataloader(im_or_video_path)
@ -242,7 +238,6 @@ class TrackingLearner(object):
out = {}
results = []
for path, img, img0 in dataloader:
# TODO logging
blob = torch.from_numpy(img).cuda().unsqueeze(0)
online_targets = self.tracker.update(blob, img0)
online_bboxes = []
@ -259,7 +254,6 @@ class TrackingLearner(object):
out[frame_id] = online_bboxes
frame_id += 1
# TODO add some option to save - in tlbr (consistent with cvbp) or tlwh (consistent with fairmot)?
return out
def get_dataloader(self, im_or_video_path: str) -> DataLoader:

Просмотреть файл

@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import argparse
import os
import os.path as osp
@ -7,186 +10,122 @@ class opts(object):
"""
Defines options for experiment settings, system settings, logging, model params,
input config, training config, testing config, and tracking params.
"""
"""
def __init__(
self,
root_dir: str = os.getcwd(),
task: str = "mot",
dataset: str = "jde",
exp_id: str = "default",
test: bool = True,
load_model: str = "",
resume: bool = True,
gpus: str = "0, 1",
num_workers: int = 8,
not_cuda_benchmark: bool = True,
seed: int = 317,
print_iter: int = 0,
hide_data_time: bool = True,
save_all: bool = True,
metric: str = "loss",
vis_thresh: float = 0.5,
save_all: bool = False,
arch: str = "dla_34",
head_conv: int = -1,
down_ratio: int = 4,
input_res: int = -1,
input_h: int = -1,
input_w: int = -1,
lr: float = 1e-4,
lr_step: str = "20,27",
num_epochs: int = 30,
batch_size: int = 12,
master_batch_size: int = -1,
num_iters: int = -1,
val_intervals: int = 5,
trainval: bool = True,
K: int = 128,
not_prefetch_test: bool = True,
fix_res: bool = True,
keep_res: bool = True,
test_mot16: bool = False,
val_mot15: bool = False,
test_mot15: bool = False,
val_mot16: bool = False,
test_mot17: bool = False,
val_mot17: bool = False,
val_mot20: bool = False,
test_mot20: bool = False,
conf_thres: float = 0.6,
det_thres: float = 0.3,
nms_thres: float = 0.4,
track_buffer: int = 30,
min_box_area: float = 200,
input_video: str = "../videos/MOT16-03.mp4",
output_format: str = "video",
output_root: str = "../results",
data_cfg: str = "../src/lib/cfg/data.json",
data_dir: str = "/data/yfzhang/MOT/JDE",
mse_loss: bool = True,
reg_loss: str = "l1",
hm_weight: float = 1,
off_weight: float = 1,
wh_weight: float = 0.1,
id_loss: str = "ce",
id_weight: float = 1,
reid_dim: int = 512,
norm_wh: bool = True,
dense_wh: bool = True,
cat_spec_wh: bool = True,
not_reg_offset: bool = True,
) -> None:
opt = argparse.Namespace()
self._init_opt()
# basic experiment setting
opt.task = task
opt.dataset = dataset
opt.exp_id = exp_id
opt.test = test
opt.load_model = load_model
opt.resume = resume
self.gpus = gpus
self.save_all = save_all
self.arch = arch
self.head_conv = head_conv if head_conv != -1 else 256 # init default
self.input_h = input_h
self.input_w = input_w
self.lr = lr
self.lr_step = lr_step
self.num_epochs = num_epochs
self.val_intervals = val_intervals
self.conf_thres = conf_thres
self.det_thres = det_thres
self.nms_thres = nms_thres
self.track_buffer = track_buffer
self.min_box_area = min_box_area
self.reid_dim = reid_dim
self.root_dir = root_dir
opt.gpus_str = gpus
opt.gpus = [int(gpu) for gpu in gpus.split(",")]
opt.gpus = (
[i for i in range(len(opt.gpus))] if opt.gpus[0] >= 0 else [-1]
)
opt.num_workers = num_workers
opt.not_cuda_benchmark = not_cuda_benchmark
opt.seed = seed
opt.print_iter = print_iter
opt.hide_data_time = hide_data_time
opt.save_all = save_all
opt.metric = metric
opt.vis_thresh = vis_thresh
opt.arch = arch
opt.head_conv = head_conv
if opt.head_conv == -1: # init default
opt.head_conv = 256
opt.pad = 31
opt.num_stacks = 1
opt.down_ratio = down_ratio
opt.input_res = input_res
opt.input_h = input_h
opt.input_w = input_w
opt.lr = lr
opt.lr_step = [int(i) for i in lr_step.split(",")]
opt.num_epochs = num_epochs
opt.batch_size = batch_size
opt.master_batch_size = master_batch_size
if opt.master_batch_size == -1:
opt.master_batch_size = opt.batch_size // len(opt.gpus)
rest_batch_size = opt.batch_size - opt.master_batch_size
opt.chunk_sizes = [opt.master_batch_size]
for i in range(len(opt.gpus) - 1):
slave_chunk_size = rest_batch_size // (len(opt.gpus) - 1)
if i < rest_batch_size % (len(opt.gpus) - 1):
slave_chunk_size += 1
opt.chunk_sizes.append(slave_chunk_size)
opt.num_iters = num_iters
opt.val_intervals = val_intervals
opt.trainval = trainval
if opt.trainval:
opt.val_intervals = 100000000
opt.K = K
opt.not_prefetch_test = not_prefetch_test
opt.fix_res = fix_res
opt.keep_res = keep_res
opt.fix_res = not keep_res
opt.test_mot16 = test_mot16
opt.val_mot15 = val_mot15
opt.test_mot15 = test_mot15
opt.val_mot16 = val_mot16
opt.test_mot16 = test_mot16
opt.val_mot17 = val_mot17
opt.val_mot20 = val_mot20
opt.test_mot20 = test_mot20
opt.conf_thres = conf_thres
opt.det_thres = det_thres
opt.nms_thres = nms_thres
opt.track_buffer = track_buffer
opt.min_box_area = min_box_area
opt.input_video = input_video
opt.output_format = output_format
opt.output_root = output_root
opt.data_cfg = data_cfg
opt.data_dir = data_dir
opt.mse_loss = mse_loss
opt.reg_loss = reg_loss
opt.hm_weight = hm_weight
opt.off_weight = off_weight
opt.wh_weight = wh_weight
opt.id_loss = id_loss
opt.id_weight = id_weight
opt.reid_dim = reid_dim
opt.norm_wh = norm_wh
opt.dense_wh = dense_wh
opt.cat_spec_wh = cat_spec_wh
opt.not_reg_offset = not_reg_offset
opt.reg_offset = not opt.not_reg_offset
opt.root_dir = root_dir
opt.exp_dir = osp.join(opt.root_dir, "exp", opt.task)
opt.save_dir = osp.join(opt.exp_dir, opt.exp_id)
opt.debug_dir = osp.join(opt.save_dir, "debug")
if opt.resume and opt.load_model == "":
model_path = (
opt.save_dir[:-4]
if opt.save_dir.endswith("TEST")
else opt.save_dir
)
opt.load_model = osp.join(model_path, "model_last.pth")
self.opt = opt
self._init_batch_sizes(batch_size=12, master_batch_size=-1)
self._init_dataset_info()
def _init_opt(self) -> None:
""" Default values for params that aren't exposed by TrackingLearner """
self._opt = argparse.Namespace()
self._opt.task = "mot"
self._opt.dataset = "jde"
self._opt.exp_id = "default"
self._opt.test = False
self._opt.load_model = ""
self._opt.resume = False
self._opt.num_workers = 8
self._opt.not_cuda_benchmark = False
self._opt.seed = 317
self._opt.print_iter = 0
self._opt.hide_data_time = False
self._opt.metric = "loss"
self._opt.vis_thresh = 0.5
self._opt.pad = 31
self._opt.num_stacks = 1
self._opt.down_ratio = 4
self._opt.input_res = -1
self._opt.num_iters = -1
self._opt.trainval = False
self._opt.K = 128
self._opt.not_prefetch_test = True
self._opt.keep_res = False
self._opt.fix_res = not self._opt.keep_res
self._opt.test_mot16 = False
self._opt.val_mot15 = False
self._opt.test_mot15 = False
self._opt.val_mot16 = False
self._opt.test_mot16 = False
self._opt.val_mot17 = False
self._opt.val_mot20 = False
self._opt.test_mot20 = False
self._opt.input_video = ""
self._opt.output_format = "video"
self._opt.output_root = ""
self._opt.data_cfg = ""
self._opt.data_dir = ""
self._opt.mse_loss = False
self._opt.hm_gauss = 8
self._opt.reg_loss = "l1"
self._opt.hm_weight = 1
self._opt.off_weight = 1
self._opt.wh_weight = 0.1
self._opt.id_loss = "ce"
self._opt.id_weight = 1
self._opt.norm_wh = False
self._opt.dense_wh = False
self._opt.cat_spec_wh = False
self._opt.not_reg_offset = False
self._opt.reg_offset = not self._opt.not_reg_offset
def _init_batch_sizes(self, batch_size, master_batch_size) -> None:
self._opt.batch_size = batch_size
self._opt.master_batch_size = (
master_batch_size
if master_batch_size != -1
else self._opt.batch_size // len(self._opt.gpus)
)
rest_batch_size = self._opt.batch_size - self._opt.master_batch_size
self._opt.chunk_sizes = [self._opt.master_batch_size]
for i in range(len(self.gpus) - 1):
chunk = rest_batch_size // (len(self._opt.gpus) - 1)
if i < rest_batch_size % (len(self._opt.gpus) - 1):
chunk += 1
self._opt.chunk_sizes.append(chunk)
def _init_dataset_info(self) -> None:
default_dataset_info = {
"mot": {
@ -204,48 +143,247 @@ class opts(object):
for k, v in entries.items():
self.__setattr__(k, v)
dataset = Struct(default_dataset_info[self.opt.task])
self.opt.dataset = dataset.dataset
dataset = Struct(default_dataset_info[self._opt.task])
self._opt.dataset = dataset.dataset
self.update_dataset_info_and_set_heads(dataset)
def update_dataset_res(self, input_h, input_w) -> None:
self.opt.input_h = input_h
self.opt.input_w = input_w
self.opt.output_h = self.opt.input_h // self.opt.down_ratio
self.opt.output_w = self.opt.input_w // self.opt.down_ratio
self.opt.input_res = max(self.opt.input_h, self.opt.input_w)
self.opt.output_res = max(self.opt.output_h, self.opt.output_w)
self._opt.input_h = input_h
self._opt.input_w = input_w
self._opt.output_h = self._opt.input_h // self._opt.down_ratio
self._opt.output_w = self._opt.input_w // self._opt.down_ratio
self._opt.input_res = max(self._opt.input_h, self._opt.input_w)
self._opt.output_res = max(self._opt.output_h, self._opt.output_w)
def update_dataset_info_and_set_heads(self, dataset) -> None:
input_h, input_w = dataset.default_resolution
self.opt.mean, self.opt.std = dataset.mean, dataset.std
self.opt.num_classes = dataset.num_classes
self._opt.mean, self._opt.std = dataset.mean, dataset.std
self._opt.num_classes = dataset.num_classes
# input_h(w): opt.input_h overrides opt.input_res overrides dataset default
input_h = self.opt.input_res if self.opt.input_res > 0 else input_h
input_w = self.opt.input_res if self.opt.input_res > 0 else input_w
self.opt.input_h = (
self.opt.input_h if self.opt.input_h > 0 else input_h
)
self.opt.input_w = (
self.opt.input_w if self.opt.input_w > 0 else input_w
)
self.opt.output_h = self.opt.input_h // self.opt.down_ratio
self.opt.output_w = self.opt.input_w // self.opt.down_ratio
self.opt.input_res = max(self.opt.input_h, self.opt.input_w)
self.opt.output_res = max(self.opt.output_h, self.opt.output_w)
input_h = self._opt.input_res if self._opt.input_res > 0 else input_h
input_w = self._opt.input_res if self._opt.input_res > 0 else input_w
self.input_h = self._opt.input_h if self._opt.input_h > 0 else input_h
self.input_w = self._opt.input_w if self._opt.input_w > 0 else input_w
self._opt.output_h = self._opt.input_h // self._opt.down_ratio
self._opt.output_w = self._opt.input_w // self._opt.down_ratio
self._opt.input_res = max(self._opt.input_h, self._opt.input_w)
self._opt.output_res = max(self._opt.output_h, self._opt.output_w)
if self.opt.task == "mot":
self.opt.heads = {
"hm": self.opt.num_classes,
if self._opt.task == "mot":
self.heads = {
"hm": self._opt.num_classes,
"wh": 2
if not self.opt.cat_spec_wh
else 2 * self.opt.num_classes,
"id": self.opt.reid_dim,
if not self._opt.cat_spec_wh
else 2 * self._opt.num_classes,
"id": self._opt.reid_dim,
}
if self.opt.reg_offset:
if self._opt.reg_offset:
self.heads.update({"reg": 2})
self.opt.nID = dataset.nID
self.opt.img_size = (self.opt.input_w, self.opt.input_h)
self._opt.nID = dataset.nID
self._opt.img_size = (self._opt.input_w, self._opt.input_h)
else:
assert 0, "task not defined"
### getters and setters ###
@property
def gpus(self):
return self._gpus
@gpus.setter
def gpus(self, value):
self._gpus_str = value
gpus_list = [int(gpu) for gpu in value.split(",")]
self._gpus = (
[i for i in range(len(gpus_list))] if gpus_list[0] >= 0 else [-1]
)
self._opt.gpus_str = self._gpus_str
self._opt.gpus = self._gpus
@property
def save_all(self):
return self._save_all
@save_all.setter
def save_all(self, value):
self._save_all = value
self._opt.save_all = self._save_all
@property
def arch(self):
return self._arch
@arch.setter
def arch(self, value):
self._arch = value
self._opt.arch = self._arch
@property
def head_conv(self):
return self._head_conv
@head_conv.setter
def head_conv(self, value):
self._head_conv = value
self._opt.head_conv = self._head_conv
@property
def input_h(self):
return self._input_h
@input_h.setter
def input_h(self, value):
self._input_h = value
self._opt.input_h = self._input_h
@property
def input_w(self):
return self._input_w
@input_w.setter
def input_w(self, value):
self._input_w = value
self._opt.input_w = self._input_w
@property
def lr(self):
return self._lr
@lr.setter
def lr(self, value):
self._lr = value
self._opt.lr = self._lr
@property
def lr_step(self):
return self._lr_step
@lr_step.setter
def lr_step(self, value):
self._lr_step = [int(i) for i in value.split(",")]
self._opt.lr_step = self._lr_step
@property
def num_epochs(self):
return self._num_epochs
@num_epochs.setter
def num_epochs(self, value):
self._num_epochs = value
self._opt.num_epochs = self._num_epochs
@property
def val_intervals(self):
return self._val_intervals
@val_intervals.setter
def val_intervals(self, value):
self._val_intervals = value
self._opt.val_intervals = self._val_intervals
@property
def conf_thres(self):
return self._conf_thres
@conf_thres.setter
def conf_thres(self, value):
self._conf_thres = value
self._opt.conf_thres = self._conf_thres
@property
def det_thres(self):
return self._det_thres
@det_thres.setter
def det_thres(self, value):
self._det_thres = value
self._opt.det_thres = self._det_thres
@property
def nms_thres(self):
return self._nms_thres
@nms_thres.setter
def nms_thres(self, value):
self._nms_thres = value
self._opt.nms_thres = self._nms_thres
@property
def track_buffer(self):
return self._track_buffer
@track_buffer.setter
def track_buffer(self, value):
self._track_buffer = value
self._opt.track_buffer = self._track_buffer
@property
def min_box_area(self):
return self._min_box_area
@min_box_area.setter
def min_box_area(self, value):
self._min_box_area = value
self._opt.min_box_area = self._min_box_area
@property
def reid_dim(self):
return self._reid_dim
@reid_dim.setter
def reid_dim(self, value):
self._reid_dim = value
self._opt.reid_dim = self._reid_dim
@property
def root_dir(self):
return self._root_dir
@root_dir.setter
def root_dir(self, value):
self._root_dir = value
self._opt.root_dir = self._root_dir
self._exp_dir = osp.join(self._root_dir, "exp", self._opt.task)
self._opt.exp_dir = self._exp_dir
self._save_dir = osp.join(self._exp_dir, self._opt.exp_id)
self._opt.save_dir = self._save_dir
self._debug_dir = osp.join(self._save_dir, "debug")
self._opt.debug_dir = self._debug_dir
@property
def device(self):
return self._device
@device.setter
def device(self, value):
self._device = value
self._opt.device = self._device
@property
def heads(self):
return self._heads
@heads.setter
def heads(self, value):
self._heads = value
self._opt.heads = self._heads
### getters only ####
@property
def opt(self):
return self._opt
@property
def task(self):
return self._opt.task
@property
def save_dir(self):
return self.opt._save_dir
@property
def chunk_sizes(self):
return self._opt.chunk_sizes

Просмотреть файл

@ -3,7 +3,7 @@ from collections import deque
import numpy as np
import torch
import torch.nn.functional as F
from ..models import # EDITED
from ..models import * # EDITED
from ..models.decode import mot_decode # EDITED
from ..models.model import create_model, load_model # EDITED
from ..models.utils import _tranpose_and_gather_feat # EDITED

Просмотреть файл

@ -38,6 +38,7 @@ class MotLoss(torch.nn.Module):
def forward(self, outputs, batch):
opt = self.opt
hm_loss, wh_loss, off_loss, id_loss = 0, 0, 0, 0
for s in range(opt.num_stacks):
output = outputs[s]
if not opt.mse_loss: