Skip to content

Commit ba1a949

Browse files
committed
major refactoring
1 parent 014e74c commit ba1a949

21 files changed

+658
-946
lines changed

.gitignore

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
# Python cache
12
*.pyc
2-
*.mexa64
33

4+
# OS X temporary metadata
5+
._*
6+
*.DS_Store
7+
8+
# Wiki page
49
wiki/
10+
11+
# Results
512
output/

.pylintrc

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[MESSAGES CONTROL]
2+
disable=missing-docstring,invalid-name,wildcard-import,unused-wildcard-import,bad-builtin,no-self-use,locally-disabled
3+
4+
[TYPECHECK]
5+
ignored-classes=numpy,theano
6+
7+
[DESIGN]
8+
# Maximum number of arguments for function / method
9+
max-args=20
10+
# Maximum number of locals for function / method body
11+
max-locals=30
12+
# Maximum number of return / yield for function / method body
13+
max-returns=10
14+
# Maximum number of branch for function / method body
15+
max-branches=12
16+
# Maximum number of statements in function / method body
17+
max-statements=200
18+
# Maximum number of attributes for a class (see R0902).
19+
max-attributes=100
20+
# Maximum number of public methods for a class (see R0904).
21+
max-public-methods=200
22+
# Maximum number of boolean expressions in a if statement
23+
max-bool-expr=10

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
1. Download `ShapeNetCore` dataset
66
2. Set the `MODEL_ROOT_PATH` in `lib/config.py` to the extracted `ShapeNetCore`
77
3. Download model lists from the website. Some models do not have any faces.
8-
4. Generate dataset `json` file by running `python tools/generate_category_list.py`
8+
4. Generate dataset `json` file by running `python tools/gen_category_list.py`
99
5. Voxelize all the models by running `python tools/voxelize_models.py`
1010
6. Render all the models by runnning `python tools/render_models.py`. To run this step, you have to setup `blender`.
1111
7. Set `cfg.DIR.MODEL_PATH`, `cfg.DIR.RENDERING_PATH` and `cfg.DIR.VOXEL_PATH` in `lib/config.py` accoringly

_init_paths.py

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
""" Add required paths to the PYTHONPATH """
2+
3+
import os.path as osp
4+
import sys
5+
6+
7+
def add_path(path):
8+
if path not in sys.path:
9+
sys.path.insert(0, path)
10+
11+
this_dir = osp.dirname(__file__)
12+
13+
# Add lib to PYTHONPATH
14+
add_path(osp.join(this_dir, 'lib'))

experiments/scripts/mv_deep_res_gru_net_3x3x3.sh

+20-19
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,24 @@ echo Logging output to "$LOG"
1818

1919
export THEANO_FLAGS="floatX=float32,device=gpu,assert_no_cpu_op='raise'"
2020

21-
python3 ./tools/train.py \
22-
--cfg ./experiments/cfgs/shapenet_1000.yaml \
23-
--cfg ./experiments/cfgs/random_crop.yaml \
24-
--cfg ./experiments/cfgs/no_random_background.yaml \
25-
--cfg ./experiments/cfgs/max_5_views.yaml \
26-
--cfg ./experiments/cfgs/local_shapenet.yaml \
27-
--cfg ./experiments/cfgs/batch_size_24.yaml \
28-
--out $OUT_PATH \
29-
--model $NET_NAME \
30-
${*:1}
21+
python main.py \
22+
--batch-size 24 \
23+
--cfg ./experiments/cfgs/shapenet_1000.yaml \
24+
--cfg ./experiments/cfgs/random_crop.yaml \
25+
--cfg ./experiments/cfgs/no_random_background.yaml \
26+
--cfg ./experiments/cfgs/max_5_views.yaml \
27+
--cfg ./experiments/cfgs/local_shapenet.yaml \
28+
--out $OUT_PATH \
29+
--model $NET_NAME \
30+
${*:1}
3131

32-
python3 ./tools/test.py \
33-
--cfg ./experiments/cfgs/shapenet_1000.yaml \
34-
--cfg ./experiments/cfgs/no_random_background.yaml \
35-
--cfg ./experiments/cfgs/max_5_views.yaml \
36-
--cfg ./experiments/cfgs/local_shapenet.yaml \
37-
--cfg ./experiments/cfgs/batch_size_24.yaml \
38-
--weights $OUT_PATH/weights.npy \
39-
--model $NET_NAME \
40-
${*:1}
32+
python main.py \
33+
--test \
34+
--batch-size 24 \
35+
--cfg ./experiments/cfgs/shapenet_1000.yaml \
36+
--cfg ./experiments/cfgs/no_random_background.yaml \
37+
--cfg ./experiments/cfgs/max_5_views.yaml \
38+
--cfg ./experiments/cfgs/local_shapenet.yaml \
39+
--weights $OUT_PATH/weights.npy \
40+
--model $NET_NAME \
41+
${*:1}

lib/config.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
__C.CONST.BATCH_SIZE = 36
2525
__C.CONST.RECNET = 'rec_net'
2626
__C.CONST.WEIGHTS = '/scratch/chrischoy/mv_deep_res_gru_net_3x3x3/max_5_views_no_rnd_bg/weights.npy.39999.npy' # when set, load the weights from the file
27-
__C.CONST.IMAGE_MEAN = np.load('mean.npz')['mean']
27+
__C.CONST.IMAGE_MEAN = np.load('./models/data/shapenet_mean.npz')['mean']
2828

2929
#
3030
# Directories
@@ -54,6 +54,8 @@
5454
__C.TRAIN.WORKER_CAPACITY = 1000 # if use OSG, load only limited number of models at a time
5555
__C.TRAIN.NUM_RENDERING = 24
5656
__C.TRAIN.NUM_VALIDATION_ITERATIONS = 24
57+
__C.TRAIN.VALIDATION_FREQ = 2000
58+
__C.TRAIN.NAN_CHECK_FREQ = 2000
5759
__C.TRAIN.RANDOM_NUM_VIEWS = True # feed in random # views if n_views > 1
5860

5961
__C.QUEUE_SIZE = 15 # maximum number of minibatches that can be put in a data queue
@@ -62,9 +64,7 @@
6264
__C.TRAIN.RANDOM_CROP = True
6365
__C.TRAIN.PAD_X = 10
6466
__C.TRAIN.PAD_Y = 10
65-
__C.TRAIN.HUE_CHANGE = True
6667
__C.TRAIN.FLIP = True
67-
__C.TRAIN.HUE_RANGE = 0.1
6868

6969
# For no random bg images, add random colors
7070
__C.TRAIN.NO_BG_COLOR_RANGE = [[225, 255], [225, 255], [225, 255]]
@@ -83,7 +83,7 @@
8383
# after the training almost converged since weight can increase indefinitely
8484
# (for cross entropy loss). Too high regularization will also hinder training.
8585
__C.TRAIN.WEIGHT_DECAY = 0.00005
86-
86+
__C.TRAIN.LOSS_LIMIT = 2 # stop training if the loss exceeds the limit
8787
__C.TRAIN.SAVE_FREQ = 10000 # weights will be overwritten every save_freq
8888
__C.TRAIN.PRINT_FREQ = 40
8989

@@ -93,7 +93,7 @@
9393
# Scale: scale 1/255
9494
# Center: subtract mean from the image
9595
###############################################################################
96-
__C.TRAIN.PREPROCESSING_TYPE = 'center' # ['scale', 'center']
96+
__C.TRAIN.PREPROCESSING_TYPE = 'scale' # ['scale', 'center']
9797

9898
#
9999
# Testing options

lib/data_augmentation.py

+8-78
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,26 @@
1-
#!/usr/bin/env python3
2-
31
import numpy as np
42
from lib.config import cfg
53
from PIL import Image
64

75

8-
def rgb_to_hsv(rgb):
9-
# Translated from source of colorsys.rgb_to_hsv
10-
# r,g,b should be a numpy arrays with values between 0 and 255
11-
# rgb_to_hsv returns an array of floats between 0.0 and 1.0.
12-
rgb = rgb.astype(np.float32)
13-
hsv = np.zeros_like(rgb)
14-
# in case an RGBA array was passed, just copy the A channel
15-
hsv[..., 3:] = rgb[..., 3:]
16-
r, g, b = rgb[..., 0], rgb[..., 1], rgb[..., 2]
17-
maxc = np.max(rgb[..., :3], axis=-1)
18-
minc = np.min(rgb[..., :3], axis=-1)
19-
hsv[..., 2] = maxc
20-
mask = maxc != minc
21-
hsv[mask, 1] = (maxc - minc)[mask] / maxc[mask]
22-
rc = np.zeros_like(r)
23-
gc = np.zeros_like(g)
24-
bc = np.zeros_like(b)
25-
rc[mask] = (maxc - r)[mask] / (maxc - minc)[mask]
26-
gc[mask] = (maxc - g)[mask] / (maxc - minc)[mask]
27-
bc[mask] = (maxc - b)[mask] / (maxc - minc)[mask]
28-
hsv[..., 0] = np.select([r == maxc, g == maxc],
29-
[bc - gc, 2.0 + rc - bc],
30-
default=4.0 + gc - rc)
31-
hsv[..., 0] = (hsv[..., 0] / 6.0) % 1.0
32-
return hsv
33-
34-
35-
def hsv_to_rgb(hsv):
36-
# Translated from source of colorsys.hsv_to_rgb
37-
# h,s should be a numpy arrays with values between 0.0 and 1.0
38-
# v should be a numpy array with values between 0.0 and 255.0
39-
# hsv_to_rgb returns an array of uints between 0 and 255.
40-
rgb = np.empty_like(hsv)
41-
rgb[..., 3:] = hsv[..., 3:]
42-
h, s, v = hsv[..., 0], hsv[..., 1], hsv[..., 2]
43-
i = (h * 6.0).astype('uint8')
44-
f = (h * 6.0) - i
45-
p = v * (1.0 - s)
46-
q = v * (1.0 - s * f)
47-
t = v * (1.0 - s * (1.0 - f))
48-
i = i % 6
49-
conditions = [s == 0.0, i == 1, i == 2, i == 3, i == 4, i == 5]
50-
rgb[..., 0] = np.select(conditions, [v, q, p, p, t, v], default=v)
51-
rgb[..., 1] = np.select(conditions, [v, v, v, q, p, p], default=t)
52-
rgb[..., 2] = np.select(conditions, [v, p, t, v, v, q], default=p)
53-
return rgb.astype('uint8')
54-
55-
56-
def shift_hue(arr, hout):
57-
hsv = rgb_to_hsv(arr)
58-
hsv[0, ...] += hout # change hue
59-
hsv[0, ...] = np.max(np.min(hsv[0, ...], 1), 0)
60-
rgb = hsv_to_rgb(hsv)
61-
return rgb
62-
63-
646
def image_transform(img, crop_x, crop_y, crop_loc=None, color_tint=None):
657
"""
668
Takes numpy.array img
679
"""
6810

6911
# Slight translation
7012
if cfg.TRAIN.RANDOM_CROP and not crop_loc:
71-
crop_loc = [0]*2
72-
crop_loc[0] = np.random.randint(0, crop_y) # corner position row
73-
crop_loc[1] = np.random.randint(0, crop_x) # corner position column
13+
crop_loc = [np.random.randint(0, crop_y),
14+
np.random.randint(0, crop_x)]
7415

7516
if crop_loc:
7617
cr, cc = crop_loc
77-
height, width, channel = img.shape
18+
height, width, _ = img.shape
7819
img_h = height - crop_y
7920
img_w = width - crop_x
80-
img = img[cr:cr+img_h, cc:cc+img_w, :]
21+
img = img[cr:cr+img_h, cc:cc+img_w]
8122
# depth = depth[cr:cr+img_h, cc:cc+img_w]
8223

83-
if cfg.TRAIN.HUE_CHANGE and not color_tint:
84-
# color tint
85-
color_tint = (np.random.rand() - 0.5) * cfg.TRAIN.HUE_RANGE
86-
87-
if color_tint:
88-
# Hue change
89-
img = shift_hue(img, color_tint)
90-
9124
if cfg.TRAIN.FLIP and np.random.rand() > 0.5:
9225
img = img[:, ::-1, ...]
9326

@@ -124,9 +57,7 @@ def add_random_background(im, background_img_fns):
12457

12558

12659
def add_random_color_background(im, color_range):
127-
r = np.random.randint(color_range[0][0], color_range[0][1] + 1)
128-
g = np.random.randint(color_range[1][0], color_range[1][1] + 1)
129-
b = np.random.randint(color_range[2][0], color_range[2][1] + 1)
60+
r, g, b = [np.random.randint(color_range[i][0], color_range[i][1] + 1) for i in range(3)]
13061

13162
if isinstance(im, Image.Image):
13263
im = np.array(im)
@@ -137,15 +68,14 @@ def add_random_color_background(im, color_range):
13768
alpha = (np.expand_dims(im[:, :, 3], axis=2) == 0).astype(np.float)
13869
im = im[:, :, :3]
13970
bg_color = np.array([[[r, g, b]]])
140-
return alpha * bg_color + im
71+
return alpha * bg_color + (1 - alpha) * im
14172

14273

14374
def test(fn):
14475
import matplotlib.pyplot as plt
14576
cfg.TRAIN.RANDOM_CROP = True
146-
cfg.TRAIN.HUE_CHANGE = True
14777
im = Image.open(fn)
148-
im = np.asarray(im)[:, :, 0:3]
149-
imt = image_transform(im, 50, 50)
78+
im = np.asarray(im)[:, :, :3]
79+
imt = image_transform(im, 10, 10)
15080
plt.imshow(imt)
15181
plt.show()

lib/data_io.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,12 @@ def model_names(model_path, model_file):
6868
models = model_names(model_path, model_file)
6969
num_models = len(models)
7070

71-
portioned_models = models[int(num_models * dataset_portion[0]):
72-
int(num_models * dataset_portion[1])]
71+
portioned_models = models[
72+
int(num_models * dataset_portion[0]):
73+
int(num_models * dataset_portion[1])
74+
]
7375

74-
category_name_pair.extend([(cat['id'], model_id)
75-
for model_id in portioned_models])
76+
category_name_pair.extend([(cat['id'], model_id) for model_id in portioned_models])
7677

7778
print('lib/data_io.py: model paths from %s' % (cfg.DATASET))
7879

0 commit comments

Comments
 (0)