Skip to content

Commit 85d8e3f

Browse files
committed
Yapf reformat
1 parent a0a1fbf commit 85d8e3f

19 files changed

+470
-586
lines changed

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 3D-R<sup>2</sup>N<sup>2</sup>: 3D Recurrent Reconstruction Neural Network
22

3-
This repository contains the source codes for the paper [Choy et al., 3D-R2N2: A Unified Approach for Single and Multi-view 3D Object Reconstruction, ECCV 2016](http://arxiv.org/abs/1604.00449). Given one or multiple views of an object, the network generates voxelized (voxel is 3D equivalent of pixel) reconstruction of the object in 3D.
3+
This repository contains the source codes for the paper [Choy et al., 3D-R2N2: A Unified Approach for Single and Multi-view 3D Object Reconstruction, ECCV 2016](http://arxiv.org/abs/1604.00449). Given one or multiple views of an object, the network generates voxelized (voxel is 3D equivalent of pixel) reconstruction of the object in 3D. This is the first work that generates a voxelized 3D reconstruction given 2D image observations using a neural network.
44

55
## Citing this work
66

@@ -22,9 +22,9 @@ If you find this work useful in your research, please consider citing:
2222

2323
Traditionally, single view reconstruction and multi view reconstruction are disjoint problmes that has been dealt using different approaches. In this work, we first propose a unified framework for both single and multi view reconstruction using a `3D Recurrent Reconstruction Neural Network` (3D-R2N2).
2424

25-
| Schematic of `3D-Convolutional LSTM` | Inputs (red cells + feature) for each cell (purple)|
26-
|:------------------------------------:|:--------------------------------------------------:|
27-
| ![3D-LSTM](imgs/lstm.png) | ![3D-LSTM](imgs/lstm_time.png) |
25+
| Schematic of the `3D-Convolutional LSTM` | Inputs (red cells + feature) for each cell (purple) |
26+
|:----------------------------------------:|:---------------------------------------------------:|
27+
| ![3D-LSTM](imgs/lstm.png) | ![3D-LSTM](imgs/lstm_time.png) |
2828

2929
We can feed in images a random order since the network is trained to be invariant to the order. The ciritical component that enables the network to be invariant to the order is the `3D-Convolutional LSTM` which we first proposed in this work. The `3D-Convolutional LSTM` selectively updates parts that are visible and keeps the parts that are self occluded (please refer to [http://cvgl.stanford.edu/3d-r2n2/](http://cvgl.stanford.edu/3d-r2n2/) for the supplementary material for analysis).
3030

demo.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ def download_model(fn):
1818
if not os.path.isfile(fn):
1919
# Download the file if doewn't exist
2020
print('Downloading a pretrained model')
21-
call(['curl', 'ftp://cs.stanford.edu/cs/cvgl/ResidualGRUNet.npy',
22-
'--create-dirs', '-o', fn])
21+
call(['curl', 'ftp://cs.stanford.edu/cs/cvgl/ResidualGRUNet.npy', '--create-dirs', '-o',
22+
fn])
2323

2424

2525
def load_demo_images():

lib/_init_paths.py

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ def add_path(path):
88
if path not in sys.path:
99
sys.path.insert(0, path)
1010

11+
1112
this_dir = osp.dirname(__file__)
1213

1314
# Add lib to PYTHONPATH

lib/config.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,14 @@
7474
__C.TRAIN.DEFAULT_LEARNING_RATE = 1e-4
7575
__C.TRAIN.POLICY = 'adam' # def: sgd, adam
7676
# The EasyDict can't use dict with integers as keys
77-
__C.TRAIN.LEARNING_RATES = {'20000': 1e-5,
78-
'60000': 1e-6}
77+
__C.TRAIN.LEARNING_RATES = {'20000': 1e-5, '60000': 1e-6}
7978
__C.TRAIN.MOMENTUM = 0.90
8079
# weight decay or regularization constant. If not set, the loss can diverge
8180
# after the training almost converged since weight can increase indefinitely
8281
# (for cross entropy loss). Too high regularization will also hinder training.
8382
__C.TRAIN.WEIGHT_DECAY = 0.00005
8483
__C.TRAIN.LOSS_LIMIT = 2 # stop training if the loss exceeds the limit
85-
__C.TRAIN.SAVE_FREQ = 10000 # weights will be overwritten every save_freq
84+
__C.TRAIN.SAVE_FREQ = 10000 # weights will be overwritten every save_freq
8685
__C.TRAIN.PRINT_FREQ = 40
8786

8887
#
@@ -117,8 +116,7 @@ def _merge_a_into_b(a, b):
117116
# the types must match, too
118117
if type(b[k]) is not type(v):
119118
raise ValueError(('Type mismatch ({} vs. {}) '
120-
'for config key: {}').format(type(b[k]),
121-
type(v), k))
119+
'for config key: {}').format(type(b[k]), type(v), k))
122120

123121
# recursively merge dicts
124122
if type(v) is edict:
@@ -130,6 +128,7 @@ def _merge_a_into_b(a, b):
130128
else:
131129
b[k] = v
132130

131+
133132
def cfg_from_file(filename):
134133
"""Load a config file and merge it into the default options."""
135134
import yaml
@@ -138,6 +137,7 @@ def cfg_from_file(filename):
138137

139138
_merge_a_into_b(yaml_cfg, __C)
140139

140+
141141
def cfg_from_list(cfg_list):
142142
"""Set config keys via list (e.g., from command line)."""
143143
from ast import literal_eval

lib/data_augmentation.py

+10-11
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@ def image_transform(img, crop_x, crop_y, crop_loc=None, color_tint=None):
1010

1111
# Slight translation
1212
if cfg.TRAIN.RANDOM_CROP and not crop_loc:
13-
crop_loc = [np.random.randint(0, crop_y),
14-
np.random.randint(0, crop_x)]
13+
crop_loc = [np.random.randint(0, crop_y), np.random.randint(0, crop_x)]
1514

1615
if crop_loc:
1716
cr, cc = crop_loc
1817
height, width, _ = img.shape
1918
img_h = height - crop_y
2019
img_w = width - crop_x
21-
img = img[cr:cr+img_h, cc:cc+img_w]
20+
img = img[cr:cr + img_h, cc:cc + img_w]
2221
# depth = depth[cr:cr+img_h, cc:cc+img_w]
2322

2423
if cfg.TRAIN.FLIP and np.random.rand() > 0.5:
@@ -28,12 +27,12 @@ def image_transform(img, crop_x, crop_y, crop_loc=None, color_tint=None):
2827

2928

3029
def crop_center(im, new_height, new_width):
31-
height = im.shape[0] # Get dimensions
30+
height = im.shape[0] # Get dimensions
3231
width = im.shape[1]
33-
left = (width - new_width)/2
34-
top = (height - new_height)/2
35-
right = (width + new_width)/2
36-
bottom = (height + new_height)/2
32+
left = (width - new_width) / 2
33+
top = (height - new_height) / 2
34+
right = (width + new_width) / 2
35+
bottom = (height + new_height) / 2
3736
return im[top:bottom, left:right]
3837

3938

@@ -48,15 +47,15 @@ def add_random_color_background(im, color_range):
4847
alpha = (np.expand_dims(im[:, :, 3], axis=2) == 0).astype(np.float)
4948
im = im[:, :, :3]
5049
bg_color = np.array([[[r, g, b]]])
51-
im = alpha * bg_color + (1 - alpha) * im
50+
im = alpha * bg_color + (1 - alpha) * im
5251

5352
return im
5453

5554

5655
def preprocess_img(im, train=True):
5756
# add random background
58-
im = add_random_color_background(im, cfg.TRAIN.NO_BG_COLOR_RANGE
59-
if train else cfg.TEST.NO_BG_COLOR_RANGE)
57+
im = add_random_color_background(im, cfg.TRAIN.NO_BG_COLOR_RANGE if train else
58+
cfg.TEST.NO_BG_COLOR_RANGE)
6059

6160
# If the image has alpha channel, remove it.
6261
im_rgb = np.array(im)[:, :, :3].astype(np.float32)

lib/data_io.py

+6-80
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import os
22
import json
3-
import scipy.io
43
from collections import OrderedDict
54

65
from lib.config import cfg
@@ -12,44 +11,15 @@ def id_to_name(id, category_list):
1211
return (k, id - v[0])
1312

1413

15-
def return_aligned_models(model_path, model_ids, num_models):
16-
""" Load metadata"""
17-
18-
def orientation_mapping(x):
19-
"""Used for Seeing 3D Chair dataset json metadata loading"""
20-
return {
21-
'left': 0,
22-
'right': 180,
23-
'up': 90,
24-
'up_left': 45,
25-
'up_right': 135,
26-
'down': -90,
27-
'down_left': -45,
28-
'down_right': -135
29-
}[x]
30-
31-
aligned_models = []
32-
for model_id in model_ids:
33-
metadata_file = open(os.path.join(model_path, model_id,
34-
"metadata.json"))
35-
model_metadata = json.load(metadata_file)
36-
metadata_file.close()
37-
38-
azimuth_offset = orientation_mapping(model_metadata['orientation'])
39-
if azimuth_offset == 0:
40-
aligned_models.append(model_id)
41-
if len(aligned_models) == num_models:
42-
return aligned_models
43-
44-
4514
def category_model_id_pair(dataset_portion=[]):
4615
'''
4716
Load category, model names from a shapenet dataset.
4817
'''
18+
4919
def model_names(model_path):
5020
""" Return model names"""
51-
model_names = [name for name in os.listdir(model_path)
52-
if os.path.isdir(os.path.join(model_path, name))]
21+
model_names = [name for name in os.listdir(model_path)
22+
if os.path.isdir(os.path.join(model_path, name))]
5323
return model_names
5424

5525
category_name_pair = [] # full path of the objs files
@@ -63,10 +33,8 @@ def model_names(model_path):
6333
models = model_names(model_path)
6434
num_models = len(models)
6535

66-
portioned_models = models[
67-
int(num_models * dataset_portion[0]):
68-
int(num_models * dataset_portion[1])
69-
]
36+
portioned_models = models[int(num_models * dataset_portion[0]):int(num_models *
37+
dataset_portion[1])]
7038

7139
category_name_pair.extend([(cat['id'], model_id) for model_id in portioned_models])
7240

@@ -84,46 +52,4 @@ def get_voxel_file(category, model_id):
8452

8553

8654
def get_rendering_file(category, model_id, rendering_id):
87-
return os.path.join(cfg.DIR.RENDERING_PATH % (category, model_id),
88-
'%02d.png' % rendering_id)
89-
90-
91-
def get_voc2012_imglist():
92-
"""Retrieves list of PASCAL image that can be used for random background."""
93-
whitelist_img = set() # Set of class-safe images to return.
94-
blacklist_img = set()
95-
classes_path = os.path.join(cfg.PASCAL.VOC2012_DIR, cfg.PASCAL.CLASSES_DIR)
96-
# Parse all class definition files for each class.
97-
for c in cfg.PASCAL.BLACKLIST_CLASSES:
98-
for file_name in cfg.PASCAL.CLASSES_FILES:
99-
class_file = os.path.join(classes_path, c + file_name)
100-
with open(class_file) as f:
101-
for line in f.readlines():
102-
image_file, class_exists = line.rstrip().split()
103-
# Add image_file to whitelist if it doesn't have any of the
104-
# blacklisted class in it.
105-
if class_exists == '-1' and image_file not in blacklist_img:
106-
whitelist_img.add(image_file)
107-
else:
108-
whitelist_img.discard(image_file)
109-
blacklist_img.add(image_file)
110-
# Return full path of whitelisted image files.
111-
return [os.path.join(cfg.PASCAL.VOC2012_DIR, cfg.PASCAL.IMGS_DIR,
112-
img + '.jpg') for img in whitelist_img]
113-
114-
115-
def get_voc2012_eval_metadata(is_train=True):
116-
"""Retrieves PASCAL dataset evaluation metadata.
117-
118-
Returns tuple of ('data', 'label').
119-
'label' is an integer vector indexing 'classes'.
120-
'data' is a struct array with following perperties:
121-
['imsize', 'voc_image_id', 'voc_rec_id', 'pascal_bbox', 'view', 'kps',
122-
'part_names', 'bbox', 'poly_x', 'poly_y', 'class', 'flip', 'rotP3d',
123-
'euler', 'subtype', 'objectIndP3d']
124-
"""
125-
metadata = scipy.io.loadmat(cfg.PASCAL3D.EVAL_METADATA, squeeze_me=True)
126-
if is_train:
127-
return (metadata['train_data'], metadata['train_label'])
128-
else:
129-
return (metadata['test_data'], metadata['test_label'])
55+
return os.path.join(cfg.DIR.RENDERING_PATH % (category, model_id), '%02d.png' % rendering_id)

lib/data_process.py

+2-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import _init_paths
55

66
import sys
7-
import os
87
import time
98
import theano
109
import numpy as np
@@ -15,7 +14,7 @@
1514

1615
from lib.config import cfg
1716
from lib.data_augmentation import preprocess_img
18-
from lib.data_io import get_model_file, get_voxel_file, get_rendering_file
17+
from lib.data_io import get_voxel_file, get_rendering_file
1918

2019
import tools.binvox_rw as binvox_rw
2120

@@ -105,11 +104,7 @@ def load_label(self, path):
105104

106105
class ReconstructionDataProcess(DataProcess):
107106

108-
def __init__(self,
109-
data_queue,
110-
category_model_pair,
111-
background_imgs=[],
112-
repeat=True,
107+
def __init__(self, data_queue, category_model_pair, background_imgs=[], repeat=True,
113108
train=True):
114109
self.repeat = repeat
115110
self.train = train

0 commit comments

Comments
 (0)