Spaces:
Paused
Paused
Dean
commited on
Commit
•
a711240
1
Parent(s):
b013dfa
Preparing logging for training and evaluation, and adding evaluation step [WIP]
Browse files- dvc.lock +4 -4
- dvc.yaml +10 -2
- requirements.txt +4 -3
- src/code/custom_data_loading.py +47 -0
- src/code/eval.py +52 -0
- src/code/make_dataset.py +47 -19
- src/code/training.py +25 -38
- src/data/raw/nyu_depth_v2_labeled.mat.dvc +1 -0
- src/data/raw/splits.mat.dvc +1 -0
dvc.lock
CHANGED
@@ -3,8 +3,8 @@ process_data:
|
|
3 |
src/data/processed
|
4 |
deps:
|
5 |
- path: src/code/make_dataset.py
|
6 |
-
md5:
|
7 |
-
size:
|
8 |
- path: src/data/raw/nyu_depth_v2_labeled.mat
|
9 |
md5: 520609c519fba3ba5ac58c8fefcc3530
|
10 |
size: 2972037809
|
@@ -13,8 +13,8 @@ process_data:
|
|
13 |
size: 2626
|
14 |
outs:
|
15 |
- path: src/data/processed/
|
16 |
-
md5:
|
17 |
-
size:
|
18 |
nfiles: 2898
|
19 |
train:
|
20 |
cmd: python3 src/code/training.py src/data/processed
|
|
|
3 |
src/data/processed
|
4 |
deps:
|
5 |
- path: src/code/make_dataset.py
|
6 |
+
md5: 3a0dee3a1ba9c587b8ca6ea6f0447ada
|
7 |
+
size: 5227
|
8 |
- path: src/data/raw/nyu_depth_v2_labeled.mat
|
9 |
md5: 520609c519fba3ba5ac58c8fefcc3530
|
10 |
size: 2972037809
|
|
|
13 |
size: 2626
|
14 |
outs:
|
15 |
- path: src/data/processed/
|
16 |
+
md5: 38e5a1b51dfd29c0f313779b2f3d4540.dir
|
17 |
+
size: 234696354
|
18 |
nfiles: 2898
|
19 |
train:
|
20 |
cmd: python3 src/code/training.py src/data/processed
|
dvc.yaml
CHANGED
@@ -9,9 +9,17 @@ stages:
|
|
9 |
outs:
|
10 |
- src/data/processed/
|
11 |
train:
|
12 |
-
cmd: python3 src/code/training.py src/data/processed
|
13 |
deps:
|
14 |
- src/code/training.py
|
15 |
-
- src/data/processed/
|
16 |
outs:
|
17 |
- src/models/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
outs:
|
10 |
- src/data/processed/
|
11 |
train:
|
12 |
+
cmd: python3 src/code/training.py src/data/processed/train
|
13 |
deps:
|
14 |
- src/code/training.py
|
15 |
+
- src/data/processed/train
|
16 |
outs:
|
17 |
- src/models/
|
18 |
+
eval:
|
19 |
+
cmd: python3 src/code/eval.py src/data/processed/test
|
20 |
+
deps:
|
21 |
+
- src/code/eval.py
|
22 |
+
- src/models/model.pth
|
23 |
+
- src/data/processed/test
|
24 |
+
outs:
|
25 |
+
- src/eval/
|
requirements.txt
CHANGED
@@ -1,8 +1,9 @@
|
|
1 |
-
dvc==1.
|
2 |
-
fastai==2.
|
3 |
torch==1.7.0
|
4 |
h5py==2.10.0
|
5 |
opencv-python==4.4.0.42
|
6 |
tqdm==4.52.0
|
7 |
numpy==1.19.4
|
8 |
-
scikit-learn==0.23.2
|
|
|
|
1 |
+
dvc==1.11.15
|
2 |
+
fastai==2.2.5
|
3 |
torch==1.7.0
|
4 |
h5py==2.10.0
|
5 |
opencv-python==4.4.0.42
|
6 |
tqdm==4.52.0
|
7 |
numpy==1.19.4
|
8 |
+
scikit-learn==0.23.2
|
9 |
+
dagshub==0.1.5
|
src/code/custom_data_loading.py
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastai.vision.all import \
|
2 |
+
DataLoaders, \
|
3 |
+
delegates, \
|
4 |
+
DataBlock, \
|
5 |
+
ImageBlock, \
|
6 |
+
PILImage, \
|
7 |
+
PILImageBW, \
|
8 |
+
RandomSplitter, \
|
9 |
+
Path, \
|
10 |
+
get_files
|
11 |
+
|
12 |
+
|
13 |
+
class ImageImageDataLoaders(DataLoaders):
|
14 |
+
"""Basic wrapper around several `DataLoader`s with factory methods for Image to Image problems"""
|
15 |
+
@classmethod
|
16 |
+
@delegates(DataLoaders.from_dblock)
|
17 |
+
def from_label_func(cls, path, filenames, label_func, is_test, valid_pct=0.2, seed=None, item_transforms=None,
|
18 |
+
batch_transforms=None, **kwargs):
|
19 |
+
"""Create from list of `fnames` in `path`s with `label_func`."""
|
20 |
+
datablock = DataBlock(blocks=(ImageBlock(cls=PILImage), ImageBlock(cls=PILImageBW)),
|
21 |
+
get_y=label_func,
|
22 |
+
item_tfms=item_transforms,
|
23 |
+
batch_tfms=batch_transforms)
|
24 |
+
if not is_test:
|
25 |
+
datablock.splitter = RandomSplitter(valid_pct, seed=seed)
|
26 |
+
res = cls.from_dblock(datablock, filenames, path=path, **kwargs)
|
27 |
+
return res
|
28 |
+
|
29 |
+
|
30 |
+
def get_y_fn(x):
|
31 |
+
y = str(x.absolute()).replace('.jpg', '_depth.png')
|
32 |
+
y = Path(y)
|
33 |
+
|
34 |
+
return y
|
35 |
+
|
36 |
+
|
37 |
+
def create_data(data_path, is_test=False):
|
38 |
+
filenames = get_files(data_path, extensions='.jpg')
|
39 |
+
if len(filenames) == 0:
|
40 |
+
raise ValueError("Could not find any files in the given path")
|
41 |
+
dataset = ImageImageDataLoaders.from_label_func(data_path,
|
42 |
+
is_test=is_test,
|
43 |
+
seed=42,
|
44 |
+
bs=4, num_workers=0,
|
45 |
+
filenames=filenames,
|
46 |
+
label_func=get_y_fn)
|
47 |
+
return dataset
|
src/code/eval.py
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sys
|
2 |
+
from fastai.vision.all import unet_learner, Path, resnet34, MSELossFlat
|
3 |
+
import torch
|
4 |
+
from src.code.custom_data_loading import create_data
|
5 |
+
from dagshub.fastai import DAGsHubLogger
|
6 |
+
|
7 |
+
|
8 |
+
def compute_errors(targ, pred):
|
9 |
+
thresh = torch.max((targ / pred), (pred / targ)).numpy()
|
10 |
+
a1 = (thresh < 1.25).mean()
|
11 |
+
a2 = (thresh < 1.25 ** 2).mean()
|
12 |
+
a3 = (thresh < 1.25 ** 3).mean()
|
13 |
+
|
14 |
+
abs_rel = (torch.abs(targ - pred) / targ).mean().item()
|
15 |
+
sq_rel = torch.mean(((targ - pred).pow(2)) / targ).item()
|
16 |
+
|
17 |
+
rmse = torch.sqrt((targ - pred).pow(2).mean()).item()
|
18 |
+
|
19 |
+
rmse_log = torch.sqrt((torch.log(1 + targ) - torch.log(1 + pred)).pow(2).mean()).item()
|
20 |
+
|
21 |
+
err = torch.log(1 + pred) - torch.log(1 + targ)
|
22 |
+
silog = torch.sqrt(torch.mean(err.pow(2)) - torch.mean(err).pow(2)).item() * 100
|
23 |
+
|
24 |
+
log_10 = (torch.abs(torch.log10(1 + targ) - torch.log10(1 + pred))).mean().item()
|
25 |
+
return dict(a1=a1,
|
26 |
+
a2=a2,
|
27 |
+
a3=a3,
|
28 |
+
abs_rel=abs_rel,
|
29 |
+
sq_rel=sq_rel,
|
30 |
+
rmse=rmse,
|
31 |
+
rmse_log=rmse_log,
|
32 |
+
silog=silog,
|
33 |
+
log_10=log_10)
|
34 |
+
|
35 |
+
|
36 |
+
if __name__ == "__main__":
|
37 |
+
if len(sys.argv) < 2:
|
38 |
+
print("usage: %s <test_data_path>" % sys.argv[0], file=sys.stderr)
|
39 |
+
sys.exit(0)
|
40 |
+
|
41 |
+
data_path = Path(sys.argv[1])
|
42 |
+
data = create_data(data_path, is_test=True)
|
43 |
+
|
44 |
+
learner = unet_learner(data,
|
45 |
+
resnet34,
|
46 |
+
n_out=3,
|
47 |
+
loss_func=MSELossFlat(),
|
48 |
+
path='src/',
|
49 |
+
model_dir='models')
|
50 |
+
learner = learner.load('model')
|
51 |
+
predictions, targets = learner.get_preds()
|
52 |
+
print(compute_errors(targets, predictions))
|
src/code/make_dataset.py
CHANGED
@@ -26,11 +26,21 @@
|
|
26 |
# SOFTWARE.
|
27 |
#######################################################################################
|
28 |
#
|
29 |
-
# Helper script to convert the NYU Depth v2 dataset Matlab file into a set of
|
30 |
-
# PNG and JPEG images.
|
31 |
-
#
|
32 |
# See https://github.com/deeplearningais/curfil/wiki/Training-and-Prediction-with-the-NYU-Depth-v2-Dataset
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
from __future__ import print_function
|
35 |
|
36 |
import h5py
|
@@ -42,41 +52,57 @@ import cv2
|
|
42 |
from tqdm import tqdm
|
43 |
|
44 |
|
45 |
-
def convert_image(
|
46 |
-
|
47 |
-
|
48 |
-
|
|
|
|
|
49 |
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
|
55 |
|
56 |
if __name__ == "__main__":
|
57 |
|
58 |
-
if
|
|
|
59 |
print("usage: %s <h5_file> <train_test_split> <out_folder>" % sys.argv[0], file=sys.stderr)
|
60 |
sys.exit(0)
|
61 |
|
|
|
62 |
h5_file = h5py.File(sys.argv[1], "r")
|
63 |
-
# h5py is not able to open that file. but scipy is
|
64 |
-
train_test = scipy.io.loadmat(sys.argv[2])
|
65 |
out_folder = sys.argv[3]
|
66 |
|
|
|
67 |
test_images = set([int(x) for x in train_test["testNdxs"]])
|
68 |
train_images = set([int(x) for x in train_test["trainNdxs"]])
|
69 |
print("%d training images" % len(train_images))
|
70 |
print("%d test images" % len(test_images))
|
71 |
|
|
|
72 |
depth = h5_file['depths']
|
|
|
|
|
73 |
|
74 |
-
|
75 |
-
|
76 |
-
images = h5_file['images']
|
77 |
scenes = [u''.join(chr(c[0]) for c in h5_file[obj_ref]) for obj_ref in h5_file['sceneTypes'][0]]
|
78 |
|
79 |
-
for i, image in tqdm(enumerate(images), desc="
|
80 |
idx = int(i) + 1
|
81 |
if idx in train_images:
|
82 |
train_test = "train"
|
@@ -84,9 +110,11 @@ if __name__ == "__main__":
|
|
84 |
assert idx in test_images, "index %d neither found in training set nor in test set" % idx
|
85 |
train_test = "test"
|
86 |
|
|
|
87 |
folder = "%s/%s/%s" % (out_folder, train_test, scenes[i])
|
88 |
if not os.path.exists(folder):
|
89 |
os.makedirs(folder)
|
90 |
-
|
|
|
91 |
|
92 |
print("Finished")
|
|
|
26 |
# SOFTWARE.
|
27 |
#######################################################################################
|
28 |
#
|
|
|
|
|
|
|
29 |
# See https://github.com/deeplearningais/curfil/wiki/Training-and-Prediction-with-the-NYU-Depth-v2-Dataset
|
30 |
|
31 |
+
|
32 |
+
"""Helper script to convert the NYU Depth v2 dataset Matlab file into a set of PNG and JPEG images.
|
33 |
+
Receives 3 Files from argparse:
|
34 |
+
<h5_file> - Contains the original images, depths maps, and scene types
|
35 |
+
<train_test_split> - contains two numpy arrays with the index of the
|
36 |
+
images based on the split to train and test sets.
|
37 |
+
<out_folder> - Name of the folder to save the original and depth images.
|
38 |
+
|
39 |
+
Every image in the DB will have it's twine B&W image that indicates the depth
|
40 |
+
in the image. the images will be read, converted by the convert_image function
|
41 |
+
and finally saved to path based on train test split and Scene types.
|
42 |
+
"""
|
43 |
+
|
44 |
from __future__ import print_function
|
45 |
|
46 |
import h5py
|
|
|
52 |
from tqdm import tqdm
|
53 |
|
54 |
|
55 |
+
def convert_image(index, depth_map, img, output_folder):
|
56 |
+
"""Processes data images and depth maps
|
57 |
+
:param index: int, image index
|
58 |
+
:param depth_map: numpy array, image depth - 2D array.
|
59 |
+
:param img: numpy array, the original RGB image - 3D array.
|
60 |
+
:param output_folder: path to save the image in.
|
61 |
|
62 |
+
Receives an image with it's relevant depth map.
|
63 |
+
Normalizes the depth map, and adds a 7 px boundary to the original image.
|
64 |
+
Saves both image and depth map to the appropriate processed data folder.
|
65 |
+
"""
|
66 |
+
|
67 |
+
# Normalize the depth image
|
68 |
+
normalized_depth = cv2.normalize(depth_map, None, 0, 255, cv2.NORM_MINMAX)
|
69 |
+
cv2.imwrite("%s/%05d_depth.png" % (output_folder, index), normalized_depth)
|
70 |
+
|
71 |
+
# Adding black frame to original image
|
72 |
+
img = img[:, :, ::-1] # Flipping the image from RGB to BGR for opencv
|
73 |
+
image_black_boundary = np.zeros(img.shape, dtype=np.uint8)
|
74 |
+
image_black_boundary[7:image_black_boundary.shape[0] - 6, 7:image_black_boundary.shape[1] - 6, :] = \
|
75 |
+
img[7:img.shape[0] - 6, 7:img.shape[1] - 6, :]
|
76 |
+
cv2.imwrite("%s/%05d.jpg" % (output_folder, index), image_black_boundary)
|
77 |
|
78 |
|
79 |
if __name__ == "__main__":
|
80 |
|
81 |
+
# Check if got all needed input for argparse
|
82 |
+
if len(sys.argv) != 4:
|
83 |
print("usage: %s <h5_file> <train_test_split> <out_folder>" % sys.argv[0], file=sys.stderr)
|
84 |
sys.exit(0)
|
85 |
|
86 |
+
# load arguments to variables
|
87 |
h5_file = h5py.File(sys.argv[1], "r")
|
88 |
+
train_test = scipy.io.loadmat(sys.argv[2]) # h5py is not able to open that file. but scipy is
|
|
|
89 |
out_folder = sys.argv[3]
|
90 |
|
91 |
+
# Extract images *indexes* for train and test data sets
|
92 |
test_images = set([int(x) for x in train_test["testNdxs"]])
|
93 |
train_images = set([int(x) for x in train_test["trainNdxs"]])
|
94 |
print("%d training images" % len(train_images))
|
95 |
print("%d test images" % len(test_images))
|
96 |
|
97 |
+
# Grayscale
|
98 |
depth = h5_file['depths']
|
99 |
+
print("Reading", sys.argv[1])
|
100 |
+
images = h5_file['images'] # (num_channels, height, width)
|
101 |
|
102 |
+
# Extract all sceneTypes per image - "office", "classroom", etc.
|
|
|
|
|
103 |
scenes = [u''.join(chr(c[0]) for c in h5_file[obj_ref]) for obj_ref in h5_file['sceneTypes'][0]]
|
104 |
|
105 |
+
for i, image in tqdm(enumerate(images), desc="Processing images", total=len(images)):
|
106 |
idx = int(i) + 1
|
107 |
if idx in train_images:
|
108 |
train_test = "train"
|
|
|
110 |
assert idx in test_images, "index %d neither found in training set nor in test set" % idx
|
111 |
train_test = "test"
|
112 |
|
113 |
+
# Create path to save image in
|
114 |
folder = "%s/%s/%s" % (out_folder, train_test, scenes[i])
|
115 |
if not os.path.exists(folder):
|
116 |
os.makedirs(folder)
|
117 |
+
|
118 |
+
convert_image(i, depth[i, :, :].T, image.T, folder)
|
119 |
|
120 |
print("Finished")
|
src/code/training.py
CHANGED
@@ -1,49 +1,36 @@
|
|
1 |
-
|
|
|
|
|
|
|
2 |
import sys
|
3 |
-
from fastai.vision.all import
|
4 |
-
from
|
5 |
-
|
6 |
-
|
7 |
-
class ImageImageDataLoaders(DataLoaders):
|
8 |
-
"Basic wrapper around several `DataLoader`s with factory methods for Image to Image problems"
|
9 |
-
|
10 |
-
@classmethod
|
11 |
-
@delegates(DataLoaders.from_dblock)
|
12 |
-
def from_label_func(cls, path, fnames, label_func, valid_pct=0.2, seed=None, item_tfms=None,
|
13 |
-
batch_tfms=None, **kwargs):
|
14 |
-
"Create from list of `fnames` in `path`s with `label_func`."
|
15 |
-
dblock = DataBlock(blocks=(ImageBlock(cls=PILImage), ImageBlock(cls=PILImageBW)),
|
16 |
-
splitter=RandomSplitter(valid_pct, seed=seed),
|
17 |
-
get_y=label_func,
|
18 |
-
item_tfms=item_tfms,
|
19 |
-
batch_tfms=batch_tfms)
|
20 |
-
res = cls.from_dblock(dblock, fnames, path=path, **kwargs)
|
21 |
-
return res
|
22 |
-
|
23 |
-
|
24 |
-
def get_y_fn(x):
|
25 |
-
y = str(x.absolute()).replace('.jpg', '_depth.png')
|
26 |
-
y = Path(y)
|
27 |
-
|
28 |
-
return y
|
29 |
-
|
30 |
-
|
31 |
-
def create_data(data_path):
|
32 |
-
fnames = get_files(data_path / 'train', extensions='.jpg')
|
33 |
-
data = ImageImageDataLoaders.from_label_func(data_path / 'train', seed=42, bs=4, num_workers=0,
|
34 |
-
fnames=fnames, label_func=get_y_fn)
|
35 |
-
return data
|
36 |
|
37 |
|
38 |
if __name__ == "__main__":
|
39 |
-
if
|
|
|
40 |
print("usage: %s <data_path>" % sys.argv[0], file=sys.stderr)
|
41 |
sys.exit(0)
|
42 |
|
43 |
data = create_data(Path(sys.argv[1]))
|
44 |
-
|
45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
print("Training model...")
|
47 |
-
learner.fine_tune(
|
48 |
print("Saving model...")
|
49 |
learner.save('model')
|
|
|
|
1 |
+
"""Trains or fine-tunes a model for the task of monocular depth estimation
|
2 |
+
Receives 1 arguments from argparse:
|
3 |
+
<data_path> - Path to the dataset which is split into 2 folders - train and test.
|
4 |
+
"""
|
5 |
import sys
|
6 |
+
from fastai.vision.all import unet_learner, Path, resnet34, rmse, MSELossFlat
|
7 |
+
from src.code.custom_data_loading import create_data
|
8 |
+
from dagshub.fastai import DAGsHubLogger
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
|
11 |
if __name__ == "__main__":
|
12 |
+
# Check if got all needed input for argparse
|
13 |
+
if len(sys.argv) != 2:
|
14 |
print("usage: %s <data_path>" % sys.argv[0], file=sys.stderr)
|
15 |
sys.exit(0)
|
16 |
|
17 |
data = create_data(Path(sys.argv[1]))
|
18 |
+
wd, lr, ep = 1e-2, 1e-3, 1
|
19 |
+
learner = unet_learner(data,
|
20 |
+
resnet34,
|
21 |
+
metrics=rmse,
|
22 |
+
wd=wd,
|
23 |
+
n_out=3,
|
24 |
+
loss_func=MSELossFlat(),
|
25 |
+
path='src/',
|
26 |
+
model_dir='models',
|
27 |
+
cbs=DAGsHubLogger(
|
28 |
+
metrics_path="train_metrics.csv",
|
29 |
+
hparams_path="train_params.yml"
|
30 |
+
))
|
31 |
+
|
32 |
print("Training model...")
|
33 |
+
learner.fine_tune(epochs=ep, base_lr=lr)
|
34 |
print("Saving model...")
|
35 |
learner.save('model')
|
36 |
+
print("Done!")
|
src/data/raw/nyu_depth_v2_labeled.mat.dvc
CHANGED
@@ -6,3 +6,4 @@ deps:
|
|
6 |
outs:
|
7 |
- md5: 520609c519fba3ba5ac58c8fefcc3530
|
8 |
path: nyu_depth_v2_labeled.mat
|
|
|
|
6 |
outs:
|
7 |
- md5: 520609c519fba3ba5ac58c8fefcc3530
|
8 |
path: nyu_depth_v2_labeled.mat
|
9 |
+
size: 2972037809
|
src/data/raw/splits.mat.dvc
CHANGED
@@ -6,3 +6,4 @@ deps:
|
|
6 |
outs:
|
7 |
- md5: 08e3c3aea27130ac7c01ffd739a4535f
|
8 |
path: splits.mat
|
|
|
|
6 |
outs:
|
7 |
- md5: 08e3c3aea27130ac7c01ffd739a4535f
|
8 |
path: splits.mat
|
9 |
+
size: 2626
|