diff --git a/models/resnet.py b/models/resnet.py
index be7a9e7..64eafea 100644
--- a/models/resnet.py
+++ b/models/resnet.py
@@ -1,40 +1,117 @@
-"""RefineNet
-
-RefineNet PyTorch for non-commercial purposes
-
-Copyright (c) 2018, Vladimir Nekrasov (vladimir.nekrasov@adelaide.edu.au)
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""
-
+# Copyright 2021 Huawei Technologies Co., Ltd
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============================================================================
 import torch.nn as nn
 import torch.nn.functional as F
 import torch
 
 import numpy as np
 
-from utils.helpers import maybe_download
-from utils.layer_factory import conv1x1, conv3x3, CRPBlock, RCUBlock
+IMG_SCALE  = 1./255
+IMG_MEAN = np.array([0.485, 0.456, 0.406]).reshape((1, 1, 3))
+IMG_STD = np.array([0.229, 0.224, 0.225]).reshape((1, 1, 3))
+
+def maybe_download(model_name, model_url, model_dir=None, map_location=None):
+    import os, sys
+    from six.moves import urllib
+    if model_dir is None:
+        torch_home = os.path.expanduser(os.getenv('TORCH_HOME', '~/.torch'))
+        model_dir = os.getenv('TORCH_MODEL_ZOO', os.path.join(torch_home, 'models'))
+    if not os.path.exists(model_dir):
+        os.makedirs(model_dir)
+    filename = '{}.pth.tar'.format(model_name)
+    cached_file = os.path.join(model_dir, filename)
+    if not os.path.exists(cached_file):
+        url = model_url
+        sys.stderr.write('Downloading: "{}" to {}\n'.format(url, cached_file))
+        urllib.request.urlretrieve(url, cached_file)
+    return torch.load(cached_file, map_location=map_location)
+
+def prepare_img(img):
+    return (img * IMG_SCALE - IMG_MEAN) / IMG_STD
+
+def batchnorm(in_planes):
+    "batch norm 2d"
+    return nn.BatchNorm2d(in_planes, affine=True, eps=1e-5, momentum=0.1)
+
+def conv3x3(in_planes, out_planes, stride=1, bias=False):
+    "3x3 convolution with padding"
+    return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
+                     padding=1, bias=bias)
+
+def conv1x1(in_planes, out_planes, stride=1, bias=False):
+    "1x1 convolution"
+    return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride,
+                     padding=0, bias=bias)
+
+def convbnrelu(in_planes, out_planes, kernel_size, stride=1, groups=1, act=True):
+    "conv-batchnorm-relu"
+    if act:
+        return nn.Sequential(nn.Conv2d(in_planes, out_planes, kernel_size, stride=stride, padding=int(kernel_size / 2.), groups=groups, bias=False),
+                             batchnorm(out_planes),
+                             nn.ReLU6(inplace=True))
+    else:
+        return nn.Sequential(nn.Conv2d(in_planes, out_planes, kernel_size, stride=stride, padding=int(kernel_size / 2.), groups=groups, bias=False),
+                             batchnorm(out_planes))
+
+class CRPBlock(nn.Module):
+
+    def __init__(self, in_planes, out_planes, n_stages, max_pooling=True):
+        super(CRPBlock, self).__init__()
+        for i in range(n_stages):
+            setattr(self, '{}_{}'.format(i + 1, 'outvar_dimred'),
+                    conv3x3(in_planes if (i == 0) else out_planes,
+                            out_planes, stride=1,
+                            bias=False))
+        self.stride = 1
+        self.n_stages = n_stages
+        if max_pooling: self.maxpool = nn.MaxPool2d(kernel_size=5, stride=1, padding=2)
+        else: self.maxpool = nn.MaxPool2d(kernel_size=1, stride=1, padding=0)
+
+    def forward(self, x):
+        top = x
+        for i in range(self.n_stages):
+            top = self.maxpool(top)
+            top = getattr(self, '{}_{}'.format(i + 1, 'outvar_dimred'))(top)
+            x = top + x
+        return x
+
+stages_suffixes = {0 : '_conv',
+                   1 : '_conv_relu_varout_dimred'}
+
+class RCUBlock(nn.Module):
+
+    def __init__(self, in_planes, out_planes, n_blocks, n_stages):
+        super(RCUBlock, self).__init__()
+        for i in range(n_blocks):
+            for j in range(n_stages):
+                setattr(self, '{}{}'.format(i + 1, stages_suffixes[j]),
+                        conv3x3(in_planes if (i == 0) and (j == 0) else out_planes,
+                                out_planes, stride=1,
+                                bias=(j == 0)))
+        self.stride = 1
+        self.n_blocks = n_blocks
+        self.n_stages = n_stages
+
+    def forward(self, x):
+        for i in range(self.n_blocks):
+            residual = x
+            for j in range(self.n_stages):
+                x = F.relu(x)
+                x = getattr(self, '{}{}'.format(i + 1, stages_suffixes[j]))(x)
+            x += residual
+        return x
 
 data_info = {
     21: 'VOC',
@@ -154,14 +231,14 @@ class RefineNet(nn.Module):
         self.p_ims1d2_outl4_dimred = conv3x3(256, 256, bias=False)
         self.adapt_stage4_b = self._make_rcu(256, 256, 2, 2)
         self.adapt_stage4_b2_joint_varout_dimred = conv3x3(256, 256, bias=False)
-        self.mflow_conv_g4_pool = self._make_crp(256, 256, 4)
+        self.mflow_conv_g4_pool = self._make_crp(256, 256, 4, max_pooling=False)
         self.mflow_conv_g4_b = self._make_rcu(256, 256, 3, 2)
 
         self.clf_conv = nn.Conv2d(256, num_classes, kernel_size=3, stride=1,
                                   padding=1, bias=True)
 
-    def _make_crp(self, in_planes, out_planes, stages):
-        layers = [CRPBlock(in_planes, out_planes,stages)]
+    def _make_crp(self, in_planes, out_planes, stages, max_pooling=True):
+        layers = [CRPBlock(in_planes, out_planes, stages, max_pooling)]
         return nn.Sequential(*layers)
     
     def _make_rcu(self, in_planes, out_planes, blocks, stages):
@@ -199,6 +276,7 @@ class RefineNet(nn.Module):
         l4 = self.do(l4)
         l3 = self.do(l3)
 
+
         x4 = self.p_ims1d2_outl1_dimred(l4)
         x4 = self.adapt_stage1_b(x4)
         x4 = self.relu(x4)
@@ -227,11 +305,13 @@ class RefineNet(nn.Module):
         x2 = self.mflow_conv_g3_b3_joint_varout_dimred(x2)
         x2 = nn.Upsample(size=l1.size()[2:], mode='bilinear', align_corners=True)(x2)
 
+
         x1 = self.p_ims1d2_outl4_dimred(l1)
         x1 = self.adapt_stage4_b(x1)
         x1 = self.adapt_stage4_b2_joint_varout_dimred(x1)
         x1 = x1 + x2
         x1 = F.relu(x1)
+
         x1 = self.mflow_conv_g4_pool(x1)
         x1 = self.mflow_conv_g4_b(x1)
         x1 = self.do(x1)