Skip to content

Commit 7d9af2e

Browse files
committed
initial commit
0 parents  commit 7d9af2e

20 files changed

+3531
-0
lines changed

.gitignore

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
**/best_models/
2+
**/checkpoints/
3+
**/tensorboard_events/
4+
###########
5+
6+
*.pyc
7+
*.pyd
8+
*.pyo
9+
__pycache__
10+
*.so
11+
*.o
12+
13+
*.egg
14+
*.egg-info
15+
.*cache*/
16+
*venv*/
17+
/.hg
18+
19+
/Cython/Build/*.c
20+
/Cython/Compiler/*.c
21+
/Cython/Debugger/*.c
22+
/Cython/Distutils/*.c
23+
/Cython/Parser/*.c
24+
/Cython/Plex/*.c
25+
/Cython/Runtime/refnanny.c
26+
/Cython/Tempita/*.c
27+
/Cython/*.c
28+
/Cython/*.html
29+
/Cython/*/*.html
30+
31+
/Tools/*.elc
32+
/Demos/*.html
33+
/Demos/*/*.html
34+
/Demos/benchmarks/*.c
35+
36+
/TEST/
37+
/TEST_TMP/
38+
/build/
39+
/cython_build/
40+
cython_debug/
41+
/wheelhouse*/
42+
!tests/build/
43+
/dist/
44+
.gitrev
45+
.coverage
46+
coverage*.xml
47+
coverage*.html
48+
/coverage*/
49+
*.patch
50+
*.diff
51+
*.orig
52+
*.prof
53+
*.rej
54+
*.log
55+
*.dep
56+
*.swp
57+
*.gz
58+
*.bz2
59+
*.xz
60+
*~
61+
callgrind.out.*
62+
63+
.ipynb_checkpoints
64+
docs/build
65+
docs/_build
66+
67+
tags
68+
TAGS
69+
MANIFEST
70+
71+
.tox
72+
73+
# Jetbrains IDE project files
74+
/.idea
75+
/*.iml
76+
77+
# Komodo EDIT/IDE project files
78+
/*.komodoproject
79+
80+
# Visual Studio Code files
81+
.vscode
82+
83+
########
84+
85+
# General
86+
.DS_Store
87+
.AppleDouble
88+
.LSOverride
89+
90+
# Icon must end with two \r
91+
Icon
92+
93+
# Thumbnails
94+
._*
95+
96+
# Files that might appear in the root of a volume
97+
.DocumentRevisions-V100
98+
.fseventsd
99+
.Spotlight-V100
100+
.TemporaryItems
101+
.Trashes
102+
.VolumeIcon.icns
103+
.com.apple.timemachine.donotpresent
104+
105+
# Directories potentially created on remote AFP share
106+
.AppleDB
107+
.AppleDesktop
108+
Network Trash Folder
109+
Temporary Items
110+
.apdisk

AUTHOR_MLRefineNet.py

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
# Retrieved from https://github.com/DrSleep/multi-task-refinenet/blob/master/src/models.py
2+
"""
3+
Real-Time Joint Semantic Segmentation and Depth Estimation Using Asymmetric Annotations for non-commercial purposes
4+
5+
Copyright (c) 2019, Vladimir Nekrasov
6+
All rights reserved.
7+
8+
Redistribution and use in source and binary forms, with or without
9+
modification, are permitted provided that the following conditions are met:
10+
11+
* Redistributions of source code must retain the above copyright notice, this
12+
list of conditions and the following disclaimer.
13+
14+
* Redistributions in binary form must reproduce the above copyright notice,
15+
this list of conditions and the following disclaimer in the documentation
16+
and/or other materials provided with the distribution.
17+
18+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28+
"""
29+
30+
import torch
31+
import torch.nn as nn
32+
import math
33+
34+
def conv3x3(in_planes, out_planes, stride=1, bias=False, dilation=1, groups=1):
35+
"3x3 convolution"
36+
return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
37+
padding=dilation, dilation=dilation, bias=bias, groups=groups)
38+
39+
def conv1x1(in_planes, out_planes, stride=1, bias=False, groups=1):
40+
"1x1 convolution"
41+
return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride,
42+
padding=0, bias=bias, groups=groups)
43+
44+
def batchnorm(in_planes):
45+
"batch norm 2d"
46+
return nn.BatchNorm2d(in_planes, affine=True, eps=1e-5, momentum=0.1)
47+
48+
def convbnrelu(in_planes, out_planes, kernel_size, stride=1, groups=1, act=True):
49+
"conv-batchnorm-relu"
50+
if act:
51+
return nn.Sequential(nn.Conv2d(in_planes, out_planes, kernel_size, stride=stride, padding=int(kernel_size / 2.), groups=groups, bias=False),
52+
batchnorm(out_planes),
53+
nn.ReLU6(inplace=True))
54+
else:
55+
return nn.Sequential(nn.Conv2d(in_planes, out_planes, kernel_size, stride=stride, padding=int(kernel_size / 2.), groups=groups, bias=False),
56+
batchnorm(out_planes))
57+
58+
class CRPBlock(nn.Module):
59+
"""CRP definition"""
60+
def __init__(self, in_planes, out_planes, n_stages, groups=False):
61+
super(CRPBlock, self).__init__()
62+
for i in range(n_stages):
63+
setattr(self, '{}_{}'.format(i + 1, 'outvar_dimred'),
64+
conv1x1(in_planes if (i == 0) else out_planes,
65+
out_planes, stride=1,
66+
bias=False, groups=in_planes if groups else 1))
67+
self.stride = 1
68+
self.n_stages = n_stages
69+
self.maxpool = nn.MaxPool2d(kernel_size=5, stride=1, padding=2)
70+
71+
def forward(self, x):
72+
top = x
73+
for i in range(self.n_stages):
74+
top = self.maxpool(top)
75+
top = getattr(self, '{}_{}'.format(i + 1, 'outvar_dimred'))(top)
76+
x = top + x
77+
return x
78+
79+
80+
class InvertedResidualBlock(nn.Module):
81+
"""Inverted Residual Block from https://arxiv.org/abs/1801.04381"""
82+
def __init__(self, in_planes, out_planes, expansion_factor, stride=1):
83+
super(InvertedResidualBlock, self).__init__()
84+
intermed_planes = in_planes * expansion_factor
85+
self.residual = (in_planes == out_planes) and (stride == 1)
86+
self.output = nn.Sequential(convbnrelu(in_planes, intermed_planes, 1),
87+
convbnrelu(intermed_planes, intermed_planes, 3, stride=stride, groups=intermed_planes),
88+
convbnrelu(intermed_planes, out_planes, 1, act=False))
89+
90+
def forward(self, x):
91+
residual = x
92+
out = self.output(x)
93+
if self.residual:
94+
return (out + residual)
95+
else:
96+
return out
97+
98+
class Net(nn.Module):
99+
"""Net Definition"""
100+
mobilenet_config = [[1, 16, 1, 1], # expansion rate, output channels, number of repeats, stride
101+
[6, 24, 2, 2],
102+
[6, 32, 3, 2],
103+
[6, 64, 4, 2],
104+
[6, 96, 3, 1],
105+
[6, 160, 3, 2],
106+
[6, 320, 1, 1],
107+
]
108+
in_planes = 32 # number of input channels
109+
num_layers = len(mobilenet_config)
110+
def __init__(self, num_classes, num_tasks=2):
111+
super(Net, self).__init__()
112+
self.num_tasks = num_tasks
113+
assert self.num_tasks in [2, 3], "Number of tasks supported is either 2 or 3, got {}".format(self.num_tasks)
114+
115+
self.layer1 = convbnrelu(3, self.in_planes, kernel_size=3, stride=2)
116+
c_layer = 2
117+
for t,c,n,s in (self.mobilenet_config):
118+
layers = []
119+
for idx in range(n):
120+
layers.append(InvertedResidualBlock(self.in_planes, c, expansion_factor=t, stride=s if idx == 0 else 1))
121+
self.in_planes = c
122+
setattr(self, 'layer{}'.format(c_layer), nn.Sequential(*layers))
123+
c_layer += 1
124+
125+
## Light-Weight RefineNet ##
126+
self.conv8 = conv1x1(320, 256, bias=False)
127+
self.conv7 = conv1x1(160, 256, bias=False)
128+
self.conv6 = conv1x1(96, 256, bias=False)
129+
self.conv5 = conv1x1(64, 256, bias=False)
130+
self.conv4 = conv1x1(32, 256, bias=False)
131+
self.conv3 = conv1x1(24, 256, bias=False)
132+
self.crp4 = self._make_crp(256, 256, 4, groups=False)
133+
self.crp3 = self._make_crp(256, 256, 4, groups=False)
134+
self.crp2 = self._make_crp(256, 256, 4, groups=False)
135+
self.crp1 = self._make_crp(256, 256, 4, groups=True)
136+
137+
self.conv_adapt4 = conv1x1(256, 256, bias=False)
138+
self.conv_adapt3 = conv1x1(256, 256, bias=False)
139+
self.conv_adapt2 = conv1x1(256, 256, bias=False)
140+
141+
self.pre_depth = conv1x1(256, 256, groups=256, bias=False)
142+
self.depth = conv3x3(256, 1, bias=True)
143+
144+
self.pre_segm = conv1x1(256, 256, groups=256, bias=False)
145+
self.segm = conv3x3(256, num_classes, bias=True)
146+
self.relu = nn.ReLU6(inplace=True)
147+
148+
if self.num_tasks == 3:
149+
self.pre_normal = conv1x1(256, 256, groups=256, bias=False)
150+
self.normal = conv3x3(256, 3, bias=True)
151+
self._initialize_weights()
152+
153+
def forward(self, x):
154+
x = self.layer1(x)
155+
x = self.layer2(x) # x / 2
156+
l3 = self.layer3(x) # 24, x / 4
157+
l4 = self.layer4(l3) # 32, x / 8
158+
l5 = self.layer5(l4) # 64, x / 16
159+
l6 = self.layer6(l5) # 96, x / 16
160+
l7 = self.layer7(l6) # 160, x / 32
161+
l8 = self.layer8(l7) # 320, x / 32
162+
l8 = self.conv8(l8)
163+
l7 = self.conv7(l7)
164+
l7 = self.relu(l8 + l7)
165+
l7 = self.crp4(l7)
166+
l7 = self.conv_adapt4(l7)
167+
l7 = nn.Upsample(size=l6.size()[2:], mode='bilinear', align_corners=False)(l7)
168+
169+
l6 = self.conv6(l6)
170+
l5 = self.conv5(l5)
171+
l5 = self.relu(l5 + l6 + l7)
172+
l5 = self.crp3(l5)
173+
l5 = self.conv_adapt3(l5)
174+
l5 = nn.Upsample(size=l4.size()[2:], mode='bilinear', align_corners=False)(l5)
175+
176+
l4 = self.conv4(l4)
177+
l4 = self.relu(l5 + l4)
178+
l4 = self.crp2(l4)
179+
l4 = self.conv_adapt2(l4)
180+
l4 = nn.Upsample(size=l3.size()[2:], mode='bilinear', align_corners=False)(l4)
181+
182+
l3 = self.conv3(l3)
183+
l3 = self.relu(l3 + l4)
184+
l3 = self.crp1(l3)
185+
186+
out_segm = self.pre_segm(l3)
187+
out_segm = self.relu(out_segm)
188+
out_segm = self.segm(out_segm)
189+
190+
out_d = self.pre_depth(l3)
191+
out_d = self.relu(out_d)
192+
out_d = self.depth(out_d)
193+
194+
if self.num_tasks == 3:
195+
out_n = self.pre_normal(l3)
196+
out_n = self.relu(out_n)
197+
out_n = self.normal(out_n)
198+
return out_segm, out_d, out_n
199+
else:
200+
return out_segm, out_d
201+
202+
def _initialize_weights(self):
203+
for m in self.modules():
204+
if isinstance(m, nn.Conv2d):
205+
m.weight.data.normal_(0, 0.01)
206+
if m.bias is not None:
207+
m.bias.data.zero_()
208+
elif isinstance(m, nn.BatchNorm2d):
209+
m.weight.data.fill_(1)
210+
m.bias.data.zero_()
211+
212+
def _make_crp(self, in_planes, out_planes, stages, groups=False):
213+
layers = [CRPBlock(in_planes, out_planes,stages, groups=groups)]
214+
return nn.Sequential(*layers)
215+
216+
def net(num_classes, num_tasks):
217+
"""Constructs the network.
218+
219+
Args:
220+
num_classes (int): the number of classes for the segmentation head to output.
221+
num_tasks (int): the number of tasks, either 2 - segm + depth, or 3 - segm + depth + normals
222+
223+
"""
224+
model = Net(num_classes, num_tasks)
225+
return model
226+
227+
228+
if __name__ == '__main__':
229+
from torchinfo import summary
230+
refine_model = net(19, 2)
231+
summary(refine_model, input_size=(1, 3, 128, 416), mode='train', col_names=("input_size", "output_size", "num_params"))

0 commit comments

Comments
 (0)