text: import inspect
  import os
  
  import numpy as np
  import tensorflow as tf
  import time
  import pickle
  
  # This Mean value is BGR order
  VGG_MEAN = [103.939, 116.779, 123.68]
  
  FLAGS = tf.app.flags.FLAGS
  
  
  class VGG16:
      def __init__(self, vgg16_npy_path=None, trainable=True):
          if vgg16_npy_path is None:
              path = inspect.getfile(VGG16)
              path = os.path.abspath(os.path.join(path, os.pardir))
              path = os.path.join(path, "vgg16.npy")
              vgg16_npy_path = path
              print(path)
          self.trainable = trainable
          self.imgs = tf.placeholder(tf.float32, [None, 224, 224, 3], name='images')
          self.labels = tf.placeholder(tf.float32, [None, FLAGS.num_classes], name='labels')
          self.var_dict = {}
          self.temp_value = None
          self.data_dict = None
          with open(vgg16_npy_path, 'rb') as f:
              self.data_dict = np.load(vgg16_npy_path, encoding='latin1').item()
          # # self.data_dict = pickle.load(f)
          #    pickle.dump(self.data_dict, f, protocol=2) 
          self.lrn_rate = 0.01
          print("npy file loaded")
          self.build()
          self.loss_layer()
  
      def build(self, train_mode=None):
          """
          load variable from npy to build the VGG
  
          :param rgb: rgb image [batch, height, width, 3] values scaled [0, 1]
          """
  
          start_time = time.time()
          print("build model started")
  
          mean = tf.constant([103.939, 116.779, 123.68], dtype=tf.float32, shape=[1, 1, 1, 3], name='img_mean')
          # images = self.imgs - mean
          # images = tf.divide(images, 128)
          # Convert RGB to BGR
          channels = tf.unstack(self.imgs, axis=-1)
          bgr = tf.stack([channels[2], channels[1], channels[0]], axis=-1)
          # red, green, blue = tf.split(self.imgs, num_or_size_splits=3, axis=3)
          # assert red.get_shape().as_list()[1:] == [224, 224, 1]
          # assert green.get_shape().as_list()[1:] == [224, 224, 1]
          # assert blue.get_shape().as_list()[1:] == [224, 224, 1]
          # bgr = tf.concat(3, [
          #    blue, green, red
          # blue - VGG_MEAN[0],
          # green - VGG_MEAN[1],
          #    red - VGG_MEAN[2]
          # ])
          bgr_mean = bgr - mean
          assert bgr.get_shape().as_list()[1:] == [224, 224, 3]
  
          self.conv1_1 = self.conv_layer(bgr_mean, 3, 64, "conv1_1")
          self.conv1_2 = self.conv_layer(self.conv1_1, 64, 64, "conv1_2")
          self.pool1 = self.max_pool(self.conv1_2, 'pool1')
  
          self.conv2_1 = self.conv_layer(self.pool1, 64, 128, "conv2_1")
          self.conv2_2 = self.conv_layer(self.conv2_1, 128, 128, "conv2_2")
          self.pool2 = self.max_pool(self.conv2_2, 'pool2')
  
          self.conv3_1 = self.conv_layer(self.pool2, 128, 256, "conv3_1")
          self.conv3_2 = self.conv_layer(self.conv3_1, 256, 256, "conv3_2")
          self.conv3_3 = self.conv_layer(self.conv3_2, 256, 256, "conv3_3")
          # self.conv3_4 = self.conv_layer(self.conv3_3, 256, 256, "conv3_4")
          self.pool3 = self.max_pool(self.conv3_3, 'pool3')
  
          self.conv4_1 = self.conv_layer(self.pool3, 256, 512, "conv4_1")
          self.conv4_2 = self.conv_layer(self.conv4_1, 512, 512, "conv4_2")
          self.conv4_3 = self.conv_layer(self.conv4_2, 512, 512, "conv4_3")
          # self.conv4_4 = self.conv_layer(self.conv4_3, 512, 512, "conv4_4")
          self.pool4 = self.max_pool(self.conv4_3, 'pool4')
  
          self.conv5_1 = self.conv_layer(self.pool4, 512, 512, "conv5_1")
          self.conv5_2 = self.conv_layer(self.conv5_1, 512, 512, "conv5_2")
          self.conv5_3 = self.conv_layer(self.conv5_2, 512, 512, "conv5_3")
          # self.conv5_4 = self.conv_layer(self.conv5_3, 512, 512, "conv5_4")
          self.pool5 = self.max_pool(self.conv5_3, 'pool5')
  
          self.fc6 = self.fc_layer(self.pool5, 25088, 4096, "fc6")  # 25088 = ((224 / (2 ** 5)) ** 2) * 512
          self.relu6 = tf.nn.relu(self.fc6)
          # if train_mode is not None:
          #    self.relu6 = tf.cond(train_mode, lambda: tf.nn.dropout(self.relu6, 0.5), lambda: self.relu6)
          # elif self.trainable:
          #    self.relu6 = tf.nn.dropout(self.relu6, 0.5)
  
          self.fc7 = self.fc_layer(self.relu6, 4096, 4096, "fc7")
          self.relu7 = tf.nn.relu(self.fc7)
          # if train_mode is not None:
          #    self.relu7 = tf.cond(train_mode, lambda: tf.nn.dropout(self.relu7, 0.5), lambda: self.relu7)
          # elif self.trainable:
          #    self.relu7 = tf.nn.dropout(self.relu7, 0.5)
  
          self.fc8 = self.fc_layer(self.relu7, 4096, FLAGS.num_classes, "fc8")
  
          self.prob = tf.nn.softmax(self.fc8, name="prob")
          self.predictions = self.prob
          # self.data_dict = None
          print("build model finished: %ds" % (time.time() - start_time))
  
      def loss_layer(self):
          logits = self.prob
          with tf.variable_scope('costs'):
              xent = tf.nn.softmax_cross_entropy_with_logits(
                  logits=logits, labels=self.labels)
              self.cost = tf.reduce_mean(xent, name='loss')
  
      def avg_pool(self, bottom, name):
          return tf.nn.avg_pool(bottom, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME', name=name)
  
      def max_pool(self, bottom, name):
          return tf.nn.max_pool(bottom, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME', name=name)
  
      def conv_layer(self, bottom, in_channels, out_channels, name):
          with tf.variable_scope(name):
              filt, conv_biases = self.get_conv_var(3, in_channels, out_channels, name)
  
              conv = tf.nn.conv2d(bottom, filt, [1, 1, 1, 1], padding='SAME')
              bias = tf.nn.bias_add(conv, conv_biases)
              relu = tf.nn.relu(bias)
  
              return relu
  
      def fc_layer(self, bottom, in_size, out_size, name):
          with tf.variable_scope(name):
              weights, biases = self.get_fc_var(in_size, out_size, name)
  
              x = tf.reshape(bottom, [-1, in_size])
              fc = tf.nn.bias_add(tf.matmul(x, weights), biases)
  
              return fc
  
      def get_conv_var(self, filter_size, in_channels, out_channels, name):
          initial_value = tf.truncated_normal([filter_size, filter_size, in_channels, out_channels], 0.0, 0.001)
          filters = self.get_var(initial_value, name, 0, name + "_filters")
  
          initial_value = tf.truncated_normal([out_channels], .0, .001)
          biases = self.get_var(initial_value, name, 1, name + "_biases")
  
          return filters, biases
  
      def get_fc_var(self, in_size, out_size, name):
          initial_value = tf.truncated_normal([in_size, out_size], 0.0, 0.001)
          weights = self.get_var(initial_value, name, 0, name + "_weights")
  
          initial_value = tf.truncated_normal([out_size], .0, .001)
          biases = self.get_var(initial_value, name, 1, name + "_biases")
  
          return weights, biases
  
      def get_var(self, initial_value, name, idx, var_name):
          if self.data_dict is not None and name in self.data_dict and name != 'fc8':
              value = self.data_dict[name][idx]
              print(name, str(idx))
          else:
              # sess = tf.Session()
              value = initial_value
              # print(name +' initializing...')
              # print('Value: ' + str(sess.run(value)))
  
          if self.trainable:
              var = tf.Variable(value, name=var_name)
          else:
              var = tf.constant(value, dtype=tf.float32, name=var_name)
  
          self.var_dict[(name, idx)] = var
  
          # print var_name, var.get_shape().as_list()
          assert var.get_shape() == initial_value.get_shape()
  
          return var
  
      def save_npy(self, sess, npy_path="./vgg19-save.npy"):
          assert isinstance(sess, tf.Session)
  
          data_dict = {}
  
          for (name, idx), var in self.var_dict.items():
              var_out = sess.run(var)
              if not name in data_dict:
                  data_dict[name] = {}
              data_dict[name][idx] = var_out
  
          np.save(npy_path, data_dict)
          print("file saved", npy_path)
          return npy_path
  
      def get_var_count(self):
          count = 0
          for v in self.var_dict.values():
              count += reduce(lambda x, y: x * y, v.get_shape().as_list())
          return count
  