├── data └── test ├── graph └── logs │ └── test ├── output ├── f_matte │ └── test └── gt_matte │ └── test ├── backup ├── checkpoint └── latest.index ├── README.md ├── layer.py ├── utils_vgg.py ├── tfrecord_utils.py ├── vgg16.py ├── train.py └── model.py /data/test: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /graph/logs/test: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /output/f_matte/test: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /output/gt_matte/test: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /backup/checkpoint: -------------------------------------------------------------------------------- 1 | model_checkpoint_path: "latest" 2 | all_model_checkpoint_paths: "latest" 3 | -------------------------------------------------------------------------------- /backup/latest.index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zylix666/DeshadowNet/HEAD/backup/latest.index -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DeshadowNet 2 | [CVPR2017] DeshadowNet: A Multi-context Embedding Deep Network for Shadow Removal
3 | TensorFlow implementation
4 | 5 | ## To Do 6 | This project is on going
7 | Does not work yet 8 | 9 | > weight decay
10 | multi-stage training
11 | multi-size training
12 | data augmentation
13 | data normalization 14 | 15 | ### Prerequisites 16 | ``` 17 | tensorflow 18 | tensorboard 19 | PIL 20 | numpy 21 | cv2 22 | ``` 23 | 24 | ## Forked code 25 | [vgg tensorflow](https://github.com/machrisaa/tensorflow-vgg)
26 | [tfboard](https://github.com/chiphuyen/stanford-tensorflow-tutorials)
27 | -------------------------------------------------------------------------------- /layer.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | 3 | def conv_layer(x, filtershape, stride, name): 4 | with tf.variable_scope(name): 5 | filters = tf.get_variable( 6 | name = 'weight', 7 | shape = filtershape, 8 | dtype = tf.float32, 9 | initializer = tf.random_normal_initializer(mean=0,stddev=0.001), 10 | trainable = True) 11 | conv = tf.nn.conv2d(x, filters, [1, stride, stride, 1], padding= 'SAME') 12 | conv_biases = tf.Variable(tf.constant(0.0, shape = [filtershape[3]], dtype = tf.float32), 13 | trainable=True, name ='bias') 14 | bias = tf.nn.bias_add(conv, conv_biases) 15 | output = prelu(bias) 16 | #output = tf.nn.dropout(prelu, keep_prob=keep_prob) 17 | img_filt = tf.reshape(filters[:,:,:,1], [-1,filtershape[0],filtershape[1],1]) 18 | tf.summary.image('conv_filter',img_filt) 19 | return output 20 | 21 | def deconv_layer(x, filtershape,output_shape, stride, name): 22 | with tf.variable_scope(name): 23 | filters = tf.get_variable( 24 | name = 'weight', 25 | shape = filtershape, 26 | dtype = tf.float32, 27 | initializer = tf.random_normal_initializer(mean=0,stddev=0.001), 28 | trainable = True) 29 | deconv = tf.nn.conv2d_transpose(x, filters, output_shape, [1, stride, stride, 1], padding ='SAME') 30 | #deconv_biases = tf.Variable(tf.constant(0.0, shape = [filtershape[3]], dtype = tf.float32), 31 | # trainable=True, name ='bias') 32 | #bias = tf.nn.bias_add(deconv, deconv_biases) 33 | #output = prelu(bias) 34 | #output = tf.nn.dropout(prelu, keep_prob=keep_prob) 35 | img_filt = tf.reshape(filters[:,:,:,1], [-1,filtershape[0],filtershape[1],1]) 36 | tf.summary.image('deconv_filter',img_filt) 37 | return prelu(deconv) 38 | 39 | def max_pool_layer(x,filtershape,stride,name): 40 | return tf.nn.max_pool(x, filtershape, [1, stride, stride, 1], padding ='SAME',name = name) 41 | 42 | def prelu(x): 43 | with tf.variable_scope('prelu'): 44 | alphas = tf.get_variable('alpha', x.get_shape()[-1], 45 | initializer=tf.constant_initializer(0.0), 46 | dtype=tf.float32) 47 | pos = tf.nn.relu(x) 48 | neg = alphas * (x - tf.abs(x)) * 0.5 49 | return pos + neg -------------------------------------------------------------------------------- /utils_vgg.py: -------------------------------------------------------------------------------- 1 | # import skimage 2 | # import skimage.io 3 | # import skimage.transform 4 | import numpy as np 5 | import cv2 6 | from PIL import Image 7 | 8 | # ============================================================ # 9 | # TODO 10 | # 1. replace skimage with image library from image completion 11 | # 2. test the vgg16_test code 12 | # 3. figure out how to import weight and model to other module 13 | # ============================================================ # 14 | 15 | # synset = [l.strip() for l in open('synset.txt').readlines()] 16 | 17 | # returns image of shape [224, 224, 3] 18 | # [height, width, depth] 19 | def load_image(path): 20 | # load image 21 | # img = skimage.io.imread(path) 22 | # img = img / 255.0 23 | img = Image.open(path) 24 | img = np.asarray(img,np.float32) 25 | img = img / 255.0 26 | assert (0 <= img).all() and (img <= 1.0).all() 27 | # print "Original Image Shape: ", img.shape 28 | # we crop image from center 29 | print('image shape: {}'.format(img.shape)) 30 | short_edge = min(img.shape[:2]) 31 | yy = int((img.shape[0] - short_edge) / 2) 32 | xx = int((img.shape[1] - short_edge) / 2) 33 | crop_img = img[yy: yy + short_edge, xx: xx + short_edge] 34 | # resize to 224, 224 35 | resized_img = cv2.resize(crop_img,(224,224),interpolation =cv2.INTER_CUBIC) 36 | # resized_img = skimage.transform.resize(crop_img, (224, 224)) 37 | return resized_img 38 | 39 | 40 | # returns the top1 string 41 | def print_prob(prob, file_path): 42 | synset = [l.strip() for l in open(file_path).readlines()] 43 | 44 | # print prob 45 | pred = np.argsort(prob)[::-1] 46 | 47 | # Get top1 label 48 | top1 = synset[pred[0]] 49 | print(("Top1: ", top1, prob[pred[0]])) 50 | # Get top5 label 51 | top5 = [(synset[pred[i]], prob[pred[i]]) for i in range(5)] 52 | print(("Top5: ", top5)) 53 | return top1 54 | 55 | 56 | # def load_image2(path, height=None, width=None): 57 | # # load image 58 | # img = skimage.io.imread(path) 59 | # img = img / 255.0 60 | # if height is not None and width is not None: 61 | # ny = height 62 | # nx = width 63 | # elif height is not None: 64 | # ny = height 65 | # nx = img.shape[1] * ny / img.shape[0] 66 | # elif width is not None: 67 | # nx = width 68 | # ny = img.shape[0] * nx / img.shape[1] 69 | # else: 70 | # ny = img.shape[0] 71 | # nx = img.shape[1] 72 | # return skimage.transform.resize(img, (ny, nx)) 73 | 74 | 75 | def test(): 76 | img = skimage.io.imread("./test_data/starry_night.jpg") 77 | ny = 300 78 | nx = img.shape[1] * ny / img.shape[0] 79 | img = skimage.transform.resize(img, (ny, nx)) 80 | skimage.io.imsave("./test_data/test/output.jpg", img) 81 | 82 | 83 | if __name__ == "__main__": 84 | test() 85 | -------------------------------------------------------------------------------- /tfrecord_utils.py: -------------------------------------------------------------------------------- 1 | ''' 2 | tfrecord utils 3 | 4 | edited version from standford tensorflow class 5 | ''' 6 | 7 | import os 8 | import sys 9 | 10 | 11 | import glob 12 | from PIL import Image 13 | import numpy as np 14 | import tensorflow as tf 15 | import matplotlib.pyplot as plt 16 | import cv2 as cv 17 | 18 | IMAGE_SIZE = 224 19 | 20 | def _int64_feature(value): 21 | return tf.train.Feature(int64_list=tf.train.Int64List(value=[value])) 22 | 23 | def _bytes_feature(value): 24 | return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value])) 25 | 26 | def get_image_binary(filename): 27 | """ You can read in the image using tensorflow too, but it's a drag 28 | since you have to create graphs. It's much easier using Pillow and NumPy 29 | """ 30 | # image = Image.open(filename) 31 | # image = np.asarray(image, np.uint8) 32 | # shape = np.array(image.shape, np.int32) 33 | 34 | image = cv.imread(filename) 35 | image = cv.resize(image, (IMAGE_SIZE, IMAGE_SIZE)) 36 | # cv.imshow('test',image) 37 | # image = cv.cvtColor(image, cv.COLOR_BGR2RGB) 38 | # cv.waitKey() 39 | image = np.asarray(image, np.uint8) 40 | shape = np.array(image.shape, np.int32) 41 | return shape.tobytes(), image.tostring() #image.tobytes() # convert image to raw data bytes in the array. 42 | 43 | def write_to_tfrecord_pair_img(writer, binary_image1, binary_image2, tfrecord_file): 44 | """ This example is to write a sample to TFRecord file. If you want to write 45 | more samples, just use a loop. 46 | """ 47 | # write label, shape, and image content to the TFRecord file 48 | example = tf.train.Example(features=tf.train.Features(feature={ 49 | 'image_input': _bytes_feature(binary_image1), 50 | 'image_gt': _bytes_feature(binary_image2) 51 | })) 52 | writer.write(example.SerializeToString()) 53 | 54 | def write_tfrecord_pair_img(writer, image_file1, image_file2, tfrecord_file): 55 | shape1 ,binary_image1 = get_image_binary(image_file1) 56 | shape2 ,binary_image2 = get_image_binary(image_file2) 57 | write_to_tfrecord_pair_img(writer, binary_image1, binary_image2, tfrecord_file) 58 | 59 | def read_from_tfrecord_pair_img(reader, filenames): 60 | tfrecord_file_queue = tf.train.string_input_producer(filenames, name='queue') 61 | _, tfrecord_serialized = reader.read(tfrecord_file_queue) 62 | 63 | # label and image are stored as bytes but could be stored as 64 | # int64 or float64 values in a serialized tf.Example protobuf. 65 | tfrecord_features = tf.parse_single_example(tfrecord_serialized, 66 | features={ 67 | 'image_input': tf.FixedLenFeature([], tf.string), 68 | 'image_gt': tf.FixedLenFeature([], tf.string), 69 | }, name='features') 70 | 71 | # image was saved as uint8, so we have to decode as uint8. 72 | img_input = tf.decode_raw(tfrecord_features['image_input'], tf.uint8) 73 | img_gt = tf.decode_raw(tfrecord_features['image_gt'], tf.uint8) 74 | 75 | # the image tensor is flattened out, so we have to reconstruct the shape 76 | img_input = tf.reshape(img_input, [IMAGE_SIZE, IMAGE_SIZE,3]) 77 | img_gt = tf.reshape(img_gt, [IMAGE_SIZE, IMAGE_SIZE,3]) 78 | return img_input, img_gt 79 | 80 | def read_tfrecord_pair_img(reader, tfrecord_file,vis): 81 | img_input, img_gt = read_from_tfrecord_pair_img(reader, [tfrecord_file]) 82 | if vis: 83 | with tf.Session() as sess: 84 | coord = tf.train.Coordinator() 85 | threads = tf.train.start_queue_runners(sess=sess, coord=coord) 86 | for i in range(4): 87 | shadow, deshadow = sess.run([img_input,img_gt]) 88 | pilimg = Image.fromarray(shadow) 89 | pilimg.show() 90 | pilimg = Image.fromarray(deshadow) 91 | pilimg.show() 92 | coord.request_stop() 93 | coord.join(threads) 94 | sess.close() 95 | 96 | return img_input, img_gt 97 | 98 | def main(): 99 | paths = glob.glob('./data/*') 100 | tfrecord_filename = './data.tfrecord' 101 | writer = tf.python_io.TFRecordWriter(tfrecord_filename) 102 | print('tf record writing start') 103 | 104 | image_size = 128; 105 | for path in paths: 106 | path = path + '/*' 107 | path = glob.glob(path) 108 | for subpath in path: 109 | x=[] 110 | if 'curry' in subpath: 111 | print('image name: {}'.format(subpath)) 112 | # write_tfrecord(writer, subpath,tfrecord_filename) 113 | write_tfrecord(writer, subpath,tfrecord_filename) 114 | 115 | writer.close() 116 | 117 | # testing tf record read1ng 118 | print('reading tf record') 119 | reader = tf.TFRecordReader() 120 | tfrecord_filename = './test.tfrecord' 121 | 122 | # closeshape, image = read_tfrecord(reader,tfrecord_filename) 123 | image, shape = read_vis_tfrecord(reader,tfrecord_filename) 124 | print('shape:{}:'.format(shape)) 125 | 126 | if __name__ == '__main__': 127 | main() 128 | -------------------------------------------------------------------------------- /vgg16.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | import os 3 | 4 | import numpy as np 5 | import tensorflow as tf 6 | import time 7 | 8 | VGG_MEAN = [103.939, 116.779, 123.68] 9 | 10 | 11 | class Vgg16: 12 | def __init__(self, vgg16_npy_path=None): 13 | if vgg16_npy_path is None: 14 | path = inspect.getfile(Vgg16) 15 | path = os.path.abspath(os.path.join(path, os.pardir)) 16 | # print(path) 17 | path = os.path.join(path, "vgg16.npy") 18 | vgg16_npy_path = path 19 | 20 | print('path to the weight of vgg: {}'.format(path)) 21 | 22 | self.data_dict = np.load(vgg16_npy_path, encoding='latin1').item() 23 | print(self.data_dict) 24 | print("npy file loaded") 25 | 26 | def build(self, x, batch_size, keep_prob): 27 | """ 28 | load variable from npy to build the VGG 29 | :param rgb: rgb image [batch, height, width, 3] values scaled [0, 255] 30 | """ 31 | 32 | #with tf.name_scope('norm_vgg_input'): 33 | # # Convert RGB to BGR 34 | # red, green, blue = tf.split(axis=3, num_or_size_splits=3, value=x) 35 | # assert red.get_shape().as_list()[1:] == [224, 224, 1] 36 | # assert green.get_shape().as_list()[1:] == [224, 224, 1] 37 | # assert blue.get_shape().as_list()[1:] == [224, 224, 1] 38 | # bgr = tf.concat(axis=3, values=[ 39 | # blue - VGG_MEAN[0], 40 | # green - VGG_MEAN[1], 41 | # red - VGG_MEAN[2], 42 | # ]) 43 | # assert bgr.get_shape().as_list()[1:] == [224, 224, 3] 44 | 45 | 46 | sess=tf.Session() 47 | print('x') 48 | print(sess.run(tf.shape(x))) 49 | self.conv1_1 = self.conv_layer(x, keep_prob, "conv1_1") 50 | self.conv1_2 = self.conv_layer(self.conv1_1, keep_prob, "conv1_2") 51 | self.pool1 = self.max_pool_stride(self.conv1_2, 2,'pool1') 52 | print('conv1') 53 | print(sess.run(tf.shape(self.pool1))) 54 | 55 | self.conv2_1 = self.conv_layer(self.pool1, keep_prob, "conv2_1") 56 | self.conv2_2 = self.conv_layer(self.conv2_1, keep_prob, "conv2_2") 57 | self.pool2 = self.max_pool_stride(self.conv2_2, 2,'pool2') 58 | print('conv2') 59 | print(sess.run(tf.shape(self.pool2))) 60 | 61 | self.conv3_1 = self.conv_layer(self.pool2, keep_prob, "conv3_1") 62 | self.conv3_2 = self.conv_layer(self.conv3_1, keep_prob, "conv3_2") 63 | self.conv3_3 = self.conv_layer(self.conv3_2, keep_prob, "conv3_3") 64 | self.pool3 = self.max_pool_stride(self.conv3_3, 2,'pool3') 65 | print('conv3') 66 | print(sess.run(tf.shape(self.pool3))) 67 | self.deconv2_1= self.deconv_layer(self.pool3,[8,8,256,256],[batch_size,112,112,256],4,"deconv2_1") 68 | print('deconv2_1') 69 | print(sess.run(tf.shape(self.deconv2_1))) 70 | 71 | self.conv4_1 = self.conv_layer(self.pool3, keep_prob, "conv4_1") 72 | self.conv4_2 = self.conv_layer(self.conv4_1, keep_prob, "conv4_2") 73 | self.conv4_3 = self.conv_layer(self.conv4_2, keep_prob, "conv4_3") 74 | self.pool4 = self.max_pool_stride(self.conv4_3, 1, 'pool4') 75 | print('conv4') 76 | print(sess.run(tf.shape(self.pool4))) 77 | 78 | self.conv5_1 = self.conv_layer(self.pool4, keep_prob, "conv5_1") 79 | self.conv5_2 = self.conv_layer(self.conv5_1, keep_prob, "conv5_2") 80 | self.conv5_3 = self.conv_layer(self.conv5_2, keep_prob, "conv5_3") 81 | self.pool5 = self.max_pool_stride(self.conv5_3, 1, 'pool5') 82 | print('conv5') 83 | print(sess.run(tf.shape(self.pool5))) 84 | 85 | 86 | # fcn layer 87 | self.fcn_1 = self.fully_conv_layer(self.pool5, [1,1,512,4096], 1, keep_prob,'fcn1') 88 | print('fcn1') 89 | print(sess.run(tf.shape(self.fcn_1))) 90 | self.fcn_2 = self.fully_conv_layer(self.fcn_1, [1,1,4096,4096], 1, keep_prob, 'fcn2') 91 | print('fcn2') 92 | print(sess.run(tf.shape(self.fcn_2))) 93 | self.fcn_3 = self.fully_conv_layer(self.fcn_2, [1,1,4096,1000], 1, keep_prob, 'fcn3') 94 | print('fcn2') 95 | print(sess.run(tf.shape(self.fcn_3))) 96 | self.deconv3_1= self.deconv_layer(self.fcn_3 ,[8,8,256,1000],[batch_size,112,112,256],4,"deconv3_1") 97 | print('deconv3_1') 98 | print(sess.run(tf.shape(self.deconv3_1))) 99 | sess.close() 100 | 101 | self.data_dict = None 102 | 103 | tf.summary.image('conv1',self.pool1[:,:,:,0:3]) 104 | tf.summary.image('conv2',self.pool2[:,:,:,0:3]) 105 | tf.summary.image('conv3',self.pool3[:,:,:,0:3]) 106 | tf.summary.image('conv4',self.pool4[:,:,:,0:3]) 107 | tf.summary.image('conv5',self.pool5[:,:,:,0:3]) 108 | tf.summary.image('conv5',self.pool5[:,:,:,0:3]) 109 | red = tf.reshape(self.deconv2_1[:,:,:,0], [-1,112,112,1]) 110 | green = tf.reshape(self.deconv2_1[:,:,:,1], [-1,112,112,1]) 111 | blue = tf.reshape(self.deconv2_1[:,:,:,2], [-1,112,112,1]) 112 | tf.summary.image('deconv2_1',red) 113 | tf.summary.image('deconv2_1',green) 114 | tf.summary.image('deconv2_1',blue) 115 | red = tf.reshape(self.deconv3_1[:,:,:,0], [-1,112,112,1]) 116 | green = tf.reshape(self.deconv3_1[:,:,:,1], [-1,112,112,1]) 117 | blue = tf.reshape(self.deconv3_1[:,:,:,2], [-1,112,112,1]) 118 | tf.summary.image('deconv3_1',red) 119 | tf.summary.image('deconv3_1',green) 120 | tf.summary.image('deconv3_1',blue) 121 | return self.deconv2_1, self.deconv3_1 122 | 123 | def max_pool_stride(self, bottom, stide, name): 124 | return tf.nn.max_pool(bottom, ksize=[1, 2, 2, 1], strides=[1, stide, stide, 1], padding='SAME', name=name) 125 | 126 | def fully_conv_layer(self, x, filtershape, stride, keep_prob, name): 127 | with tf.variable_scope(name): 128 | filters = tf.get_variable( 129 | name = 'weight', 130 | shape = filtershape, 131 | dtype = tf.float32, 132 | initializer = tf.random_normal_initializer(mean=0,stddev=0.001), 133 | trainable = True) 134 | conv = tf.nn.conv2d(x, filters, [1, stride, stride, 1], padding= 'SAME') 135 | conv_biases = tf.Variable(tf.constant(0.0, shape = [filtershape[3]], dtype = tf.float32), 136 | trainable=True, name ='bias') 137 | bias = tf.nn.bias_add(conv, conv_biases) 138 | prelu = self.prelu(bias) 139 | #output = tf.nn.dropout(prelu, keep_prob=keep_prob) 140 | return prelu 141 | 142 | def conv_layer(self, bottom, keep_prob, name): 143 | with tf.variable_scope(name): 144 | filt = self.get_conv_filter(name) 145 | conv = tf.nn.conv2d(bottom, filt, [1, 1, 1, 1], padding='SAME') 146 | conv_biases = self.get_bias(name) 147 | bias = tf.nn.bias_add(conv, conv_biases) 148 | prelu = self.prelu(bias) 149 | #output = tf.nn.dropout(prelu, keep_prob=keep_prob) 150 | return prelu 151 | 152 | def get_conv_filter(self, name): 153 | return tf.Variable(self.data_dict[name][0], name="filter") 154 | 155 | def get_bias(self, name): 156 | return tf.Variable(self.data_dict[name][1], name="biases") 157 | 158 | def get_fc_weight(self, name): 159 | return tf.Variable(self.data_dict[name][0], name="weights") 160 | 161 | def prelu(self, x): 162 | with tf.variable_scope('prelu'): 163 | alphas = tf.get_variable('alpha', x.get_shape()[-1], 164 | initializer=tf.constant_initializer(0.0), 165 | dtype=tf.float32) 166 | pos = tf.nn.relu(x) 167 | neg = alphas * (x - abs(x)) * 0.5 168 | return pos + neg 169 | 170 | def deconv_layer(self, x, filtershape,output_shape, stride, name): 171 | with tf.variable_scope(name): 172 | filters = tf.get_variable( 173 | name = 'weight', 174 | shape = filtershape, 175 | dtype = tf.float32, 176 | initializer = tf.random_normal_initializer(mean=0,stddev=0.001), 177 | trainable = True) 178 | deconv = tf.nn.conv2d_transpose(x, filters, output_shape, [1, stride, stride, 1], padding ='SAME') 179 | #deconv_biases = tf.Variable(tf.constant(0.0, shape = [filtershape[3]], dtype = tf.float32), 180 | # trainable=True, name ='bias') 181 | #bias = tf.nn.bias_add(deconv, deconv_biases) 182 | #prelu = self.prelu(bias) 183 | #output = tf.nn.dropout(prelu, keep_prob=keep_prob) 184 | return self.prelu(deconv) 185 | -------------------------------------------------------------------------------- /train.py: -------------------------------------------------------------------------------- 1 | import tqdm 2 | import cv2 3 | import numpy as np 4 | import tensorflow as tf 5 | from model import DeshadowNet 6 | from tfrecord_utils import * 7 | 8 | from tensorflow.python import debug as tf_debug 9 | 10 | IMAGE_SIZE = 224 # 64 128 224 11 | BATCH_SIZE = 2 12 | EPOCH = 50000000 13 | INIT_G_LEARNING_RATE = 1e-5 #1E-5 14 | INIT_LEARNING_RATE = 1e-4 #1E-4 15 | MOMENTUM = 0.9 16 | 17 | log_path = './graph/logs' # path to tensorboard graph 18 | TFRECORD_NAME = 'smalldata.tfrecord' 19 | 20 | # momentum to 0.9 and 21 | # weight decay to 0.0005 (at this point we do not include) 22 | 23 | ''' 24 | How to use Tensorboard 25 | Run the command line: 26 | > tensorboard --logdir=./graph/logs 27 | ''' 28 | 29 | ''' 30 | TODO 31 | 1. data needs to be normlized 32 | 2. make the test set smaller like 20 or 30 33 | 3. make the test set image size smaller 34 | 35 | ''' 36 | 37 | def make_tfrecord(): 38 | # make test set 39 | paths = glob.glob('./data/test/*') 40 | # making a list of image 41 | print('making pair of image list') 42 | image_list = [] 43 | list_flag = True 44 | for path in paths: 45 | path = glob.glob(path+'/*') 46 | index = 0 47 | for sub in path: 48 | print('image name:{}'.format(sub)) 49 | if list_flag: 50 | image_list.append([sub]) 51 | else: 52 | image_list[index].append(sub) 53 | index += 1 54 | list_flag = False 55 | 56 | 57 | # writing tf record 58 | print('tf record writing start') 59 | tfrecord_filename = TFRECORD_NAME 60 | writer = tf.python_io.TFRecordWriter(tfrecord_filename) 61 | 62 | index = 0 63 | for img_pair in image_list: 64 | index += 1 65 | print('number: {}'.format(index)) 66 | write_tfrecord_pair_img(writer, img_pair[0],img_pair[1],tfrecord_filename) 67 | 68 | writer.close() 69 | 70 | # testing tf record read1ng 71 | print('reading tf record') 72 | reader = tf.TFRecordReader() 73 | # closeshape, image = read_tfrecord(reader,tfrecord_filename) 74 | visualize = False 75 | read_tfrecord_pair_img(reader,tfrecord_filename,visualize) 76 | 77 | def train(backupFlag): 78 | # setting random seed and reset graphs 79 | 80 | G_LEARNING_RATE = 1e-5 #1e-5 81 | LEARNING_RATE = 1e-4 #1e-4 82 | 83 | tf.set_random_seed(1111) 84 | tf.reset_default_graph() 85 | 86 | #calc step number 87 | step_num = int(6 / BATCH_SIZE) 88 | 89 | # place holders for shadow image input and shadow free image input 90 | with tf.variable_scope('Data_Input'): 91 | shadow = tf.placeholder(tf.float32, [BATCH_SIZE, IMAGE_SIZE, IMAGE_SIZE, 3], name ='Shadow_image') 92 | shadow_free = tf.placeholder(tf.float32,[BATCH_SIZE,IMAGE_SIZE,IMAGE_SIZE,3], name = 'Shadow_free_image') 93 | keep_prob = tf.placeholder(tf.float32, name='keep_prob') 94 | lr_g = tf.placeholder(tf.float32, name='learn_rate_g') 95 | lr = tf.placeholder(tf.float32, name ='learn_rate_as') 96 | # init network model 97 | model = DeshadowNet(shadow, shadow_free, BATCH_SIZE,keep_prob) 98 | 99 | # gpu options for some errors 100 | config = tf.ConfigProto() 101 | config.gpu_options.allocator_type ='BFC' 102 | config.gpu_options.per_process_gpu_memory_fraction = 0.80 103 | 104 | with tf.Session() as sess: 105 | 106 | ## ==================== for tensorflow debugger ========================= ## 107 | #sess = tf_debug.LocalCLIDebugWrapperSession(sess) 108 | #sess.add_tensor_filter("has_inf_or_nan", tf_debug.has_inf_or_nan) 109 | ## ====================================================================== ## 110 | 111 | print('initializing hyperparameter ... ') 112 | #global_step = tf.Variable(0, name='global_step', trainable=False) # step size 113 | epoch = tf.Variable(0, name='epoch', trainable=False) # epoch 114 | 115 | with tf.name_scope('Momentum_Opt'): 116 | print('init optimization') 117 | opt_g = tf.train.MomentumOptimizer(lr_g, MOMENTUM) 118 | train_g_op = opt_g.minimize(model.loss, var_list = model.g_net_variables) 119 | opt_a = tf.train.MomentumOptimizer(lr, MOMENTUM) 120 | train_as_op = opt_a.minimize(model.loss, var_list = model.a_net_variables) 121 | opt_s = tf.train.MomentumOptimizer(lr, MOMENTUM) 122 | train_as_op = opt_s.minimize(model.loss, var_list = model.s_net_variables) 123 | train_op = tf.group(train_g_op,train_as_op) 124 | 125 | 126 | # loading dataset ... 127 | reader = tf.TFRecordReader() 128 | img_input, img_gt = read_tfrecord_pair_img(reader, TFRECORD_NAME, False) 129 | 130 | coord = tf.train.Coordinator() 131 | 132 | # shuffle batch ... 133 | img_input_batch,img_gt_batch = tf.train.shuffle_batch([img_input, img_gt], 134 | BATCH_SIZE, 135 | capacity=10*BATCH_SIZE, 136 | min_after_dequeue = 2*BATCH_SIZE, 137 | num_threads=4, 138 | enqueue_many=False ) 139 | 140 | print('initializing variables') 141 | init_op = tf.global_variables_initializer() 142 | init_local_op = tf.local_variables_initializer() 143 | sess.run([init_op,init_local_op]) 144 | threads = tf.train.start_queue_runners(coord = coord) 145 | 146 | # parameter 147 | tf.summary.scalar('epoch',epoch) 148 | tf.summary.scalar('loss',model.loss) 149 | tf.summary.scalar('lr_as',lr) 150 | tf.summary.scalar('lr_g',lr_g) 151 | 152 | # images 153 | tf.summary.image('F_matte',model.shadow_matte) 154 | tf.summary.image('GT_matte',model.gt_shadow_matte) 155 | tf.summary.image('F_free',model.f_shadowfree) 156 | tf.summary.image('GT_free',model.gt_shadowfree) 157 | 158 | summary_op = tf.summary.merge_all() 159 | print('start training ...') 160 | writer = tf.summary.FileWriter(log_path, graph=tf.get_default_graph()) 161 | 162 | 163 | print('check if there is backup') 164 | if backupFlag and tf.train.get_checkpoint_state('./backup'): 165 | print('backup file loading ...') 166 | saver = tf.train.Saver() 167 | saver.restore(sess, './backup/latest') 168 | else: 169 | print('no backup ...') 170 | 171 | 172 | try: 173 | while not coord.should_stop(): 174 | 175 | sess.run(tf.assign(epoch, tf.add(epoch,1))) 176 | print('epoch: {}'.format(sess.run(epoch))) 177 | if sess.run(epoch) <= EPOCH: 178 | loss_val = 0 179 | for i in tqdm.tqdm(range(step_num)): 180 | # load image batched 181 | img_input_seq, img_gt_seq = sess.run([img_input_batch,img_gt_batch]) 182 | img_input_seq.reshape([BATCH_SIZE,IMAGE_SIZE,IMAGE_SIZE,3]) 183 | img_gt_seq.reshape([BATCH_SIZE,IMAGE_SIZE,IMAGE_SIZE,3]) 184 | 185 | # type casting 186 | img_input_seq = img_input_seq.astype(np.float) 187 | img_gt_seq = img_gt_seq.astype(np.float) 188 | 189 | 190 | _,loss,summary = sess.run([train_op,model.loss,summary_op], 191 | feed_dict={ 192 | shadow: img_input_seq, 193 | shadow_free: img_gt_seq, 194 | keep_prob: 0.5, 195 | lr: LEARNING_RATE, 196 | lr_g: G_LEARNING_RATE 197 | }) 198 | # print('loss: {}'.format(loss)) 199 | loss_val += loss 200 | # write log 201 | writer.add_summary(summary, (sess.run(epoch) -1)*step_num+i) 202 | 203 | 204 | if i == int(step_num -1): 205 | A, S,SM,GT_SM = sess.run([model.A_output,model.S_output,model.shadow_matte,model.gt_shadow_matte], 206 | feed_dict={ 207 | shadow: img_input_seq, 208 | shadow_free: img_gt_seq, 209 | keep_prob: 1.0, 210 | lr: LEARNING_RATE, 211 | lr_g:G_LEARNING_RATE 212 | }) 213 | A.reshape([BATCH_SIZE,224,224,3]) 214 | S.reshape([BATCH_SIZE,224,224,3]) 215 | SM.reshape([BATCH_SIZE,224,224,3]) 216 | GT_SM.reshape([BATCH_SIZE,224,224,3]) 217 | np.savetxt('./output/a_out/A{}.out'.format("{0:06d}".format((sess.run(epoch) -1)*step_num* BATCH_SIZE+i)), A[0,:,:,0], delimiter=',') # X is an array 218 | np.savetxt('./output/s_out/S{}.out'.format("{0:06d}".format((sess.run(epoch) -1)*step_num* BATCH_SIZE+i)), S[0,:,:,0], delimiter=',') # X is an array 219 | np.savetxt('./output/sm_out/SM{}.out'.format("{0:06d}".format((sess.run(epoch) -1)*step_num* BATCH_SIZE+i)), SM[0,:,:,0], delimiter=',') # X is an array 220 | np.savetxt('./output/sm_gt_out/GT_SM{}.out'.format("{0:06d}".format((sess.run(epoch) -1)*step_num* BATCH_SIZE+i)), GT_SM[0,:,:,0], delimiter=',') # X is an array 221 | 222 | 223 | 224 | print('total loss in one epoch: {}'.format(loss_val)) 225 | 226 | # check for validation 227 | # find shadow matte 228 | #f_shadow_free, gt_shadow_free = sess.run([model.f_shadowfree,model.gt_shadowfree], 229 | # feed_dict={ 230 | # shadow: img_input_seq, 231 | # shadow_free: img_gt_seq, 232 | # keep_prob: 1.0, 233 | # lr: LEARNING_RATE, 234 | # lr_g:G_LEARNING_RATE 235 | # }) 236 | #np.savetxt('./output/f_shadow/f_shadow{}.out'.format("{0:06d}".format((sess.run(epoch) -1)*step_num* BATCH_SIZE+i)), f_shadow_free[0,:,:,:], delimiter=',') # X is an array 237 | #np.savetxt('./output/gt_shadow/gt_shadow{}.out'.format("{0:06d}".format((sess.run(epoch) -1)*step_num* BATCH_SIZE+i)), gt_shadow_free[0,:,:,:], delimiter=',') # X is an array 238 | # find 239 | #out = f_shadow_free[0].astype(np.uint8) 240 | #gt = gt_shadow_free[0].astype(np.uint8) 241 | #np.savetxt('./output/f_shadow/f_shadow{}.out'.format("{0:06d}".format((sess.run(epoch) -1)*step_num* BATCH_SIZE+i)), out[:,:,0], delimiter=',') 242 | #np.savetxt('./output/gt_shadow/gt_shadow{}.out'.format("{0:06d}".format((sess.run(epoch) -1)*step_num* BATCH_SIZE+i)), gt[:,:,0], delimiter=',') 243 | 244 | #image_show(out) 245 | #image_show(gt) 246 | 247 | #cv2.imwrite('./output/f_shadow/{}.jpg'.format("{0:06d}".format(sess.run(epoch))), cv2.cvtColor(out, cv2.COLOR_RGB2BGR)) 248 | #cv2.imwrite('./output/gt_shadow/{}.jpg'.format("{0:06d}".format(sess.run(epoch))), cv2.cvtColor(gt, cv2.COLOR_RGB2BGR)) 249 | # saving data 250 | saver = tf.train.Saver() 251 | saver.save(sess, './backup/latest', write_meta_graph = False) 252 | if sess.run(epoch) == EPOCH: 253 | saver.save(sess,'./backup/fully_trained',write_meta_graph = False) 254 | 255 | # decay learning rate 256 | if (sess.run(epoch) % 200) == 0: 257 | LEARNING_RATE = lr_decay(INIT_LEARNING_RATE, 1, sess.run(epoch)) 258 | G_LEARNING_RATE = lr_decay(INIT_G_LEARNING_RATE, 1, sess.run(epoch)) 259 | print('decreasing learning rate ...') 260 | 261 | 262 | else: 263 | print('breaking out of while loop ...') 264 | break 265 | 266 | except tf.errors.OutOfRangeError: 267 | print('ERROR: out of range\nDone Training -- epoch reached its limit') 268 | 269 | finally: 270 | print('FINAL: stop coordinate and joing thread') 271 | coord.request_stop() 272 | coord.join(threads) 273 | 274 | def image_show(np_image): 275 | img = Image.fromarray(np_image,'RGB') 276 | img.show() 277 | 278 | def lr_decay(lr_input, decay_rate,num_epoch): 279 | return lr_input / (1 + decay_rate*num_epoch) 280 | 281 | if __name__ == '__main__': 282 | make_tfrecord() 283 | train(False) 284 | -------------------------------------------------------------------------------- /model.py: -------------------------------------------------------------------------------- 1 | from layer import * 2 | import numpy as np 3 | import math 4 | from PIL import Image 5 | import vgg16 6 | import utils_vgg 7 | 8 | from tensorflow.python import debug as tf_debug 9 | 10 | ##import vgg using keras 11 | ##from keras.applications.vgg16 import VGG16 12 | ##from keras.preprocessing import image 13 | ##from keras.applications.vgg16 import preprocess_input 14 | ##from keras import backend as K 15 | #from tensorflow.python.keras.models import Model, Sequential 16 | #from tensorflow.python.keras.layers import Dense, Flatten, Dropout 17 | #from tensorflow.python.keras.applications import VGG16 18 | #from tensorflow.python.keras.applications.vgg16 import preprocess_input, decode_predictions 19 | #from tensorflow.python.keras.preprocessing.image import ImageDataGenerator 20 | #from tensorflow.python.keras.optimizers import Adam, RMSprop 21 | 22 | ## import vgg using slim 23 | #import tensorflow.contrib.slim as slim 24 | #import tensorflow.contrib.slim.nets 25 | 26 | 27 | ''' 28 | Tensorflow + Keras Example 29 | https://blog.keras.io/keras-as-a-simplified-interface-to-tensorflow-tutorial.html 30 | 31 | Keras Finetune , transfer learning 32 | https://github.com/Hvass-Labs/TensorFlow-Tutorials/blob/master/10_Fine-Tuning.ipynb 33 | https://keras.io/applications/ 34 | 35 | Tensorflow 36 | https://github.com/machrisaa/tensorflow-vgg 37 | ''' 38 | 39 | #TODO 40 | #1. choose one of the following for fine tuning 41 | # - use tf slim for loading model 42 | # - use keras and tf for loading model 43 | #2. data generate 44 | #3. check if the code works using training 45 | #4. data augmentation 46 | # - use keras if in 1 works with keras 47 | #5. data generation 48 | # - use python script to generate data within maya env 49 | 50 | MOMENTUM = 0.9 51 | VGG_MEAN = [103.939, 116.779, 123.68] 52 | 53 | class DeshadowNet: 54 | 55 | def __init__(self, x, deshadow_image, batch_size,keep_prob): 56 | 57 | self.batch_size = batch_size 58 | self.norm_x = norm_image(x) 59 | #self.norm_deshadow_image = norm_image(deshadow_image) 60 | 61 | self.A_input, self.S_input = self.G_Net(self.norm_x,keep_prob) 62 | #self.A_output = self.A_Net(self.norm_x,self.A_input,keep_prob) 63 | #self.S_output = self.S_Net(self.norm_x,self.S_input,keep_prob) 64 | self.A_output = self.A_Net(x,self.A_input,keep_prob) 65 | self.S_output = self.S_Net(x,self.S_input,keep_prob) 66 | 67 | self.shadow_matte= self.shadowMatte(self.A_output, self.S_output) 68 | self.gt_shadow_matte = self.calcShadowMatte(x, deshadow_image) 69 | 70 | # loss function 71 | self.loss = self.loss_function(self.shadow_matte, self.gt_shadow_matte) 72 | 73 | self.f_shadowfree = self.calcShadowFreeImage(x,tf.log(tf.clip_by_value(self.shadow_matte,1e-30,float('Inf')))) 74 | self.gt_shadowfree = self.calcShadowFreeImage(x,self.gt_shadow_matte) 75 | 76 | self.g_net_variables = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='G_Net') 77 | self.a_net_variables = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='A_Net') 78 | self.s_net_variables = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='S_Net') 79 | 80 | def G_Net(self,x,keep_prob): 81 | vgg = vgg16.Vgg16() 82 | print('making g-network') 83 | with tf.variable_scope('G_Net'): 84 | #x = norm_image(x) 85 | A_input, S_input = vgg.build(x, self.batch_size,keep_prob) 86 | print('finishing g-network') 87 | return A_input, S_input 88 | 89 | def A_Net(self,x,G_input,keep_prob): # after conv3 in G_Net 256 90 | 91 | print('making a-network') 92 | sess=tf.Session() 93 | with tf.variable_scope('A_Net'): 94 | 95 | # conv2-1 96 | conv2_1 = conv_layer(x,[9,9,3,96],1,'conv2-1') 97 | 98 | # pool5 99 | conv2_1_output = max_pool_layer(conv2_1,[1,3,3,1],2,'pool2-1') 100 | print('conv2-1') 101 | print(sess.run(tf.shape(conv2_1_output))) 102 | 103 | # conv2-2 104 | conv2_2_output = conv_layer(G_input,[1,1,256,64],1,'conv2-2') 105 | print('conv2-2') 106 | print(sess.run(tf.shape(conv2_2_output))) 107 | 108 | # concat conv2-1 and conv2-2 109 | conv_concat = tf.concat(axis=3, values = [conv2_1_output,conv2_2_output], name = 'concat_a_net') 110 | 111 | # conv2-3 112 | conv2_3 = conv_layer(conv_concat,[5,5,160,64],1,'conv2-3') 113 | print('conv2-3') 114 | print(sess.run(tf.shape(conv2_3))) 115 | 116 | # conv2-4 117 | conv2_4 = conv_layer(conv2_3,[5,5,64,64],1,'conv2-4') 118 | print('conv2-4') 119 | print(sess.run(tf.shape(conv2_4))) 120 | 121 | # conv2-5 122 | conv2_5 = conv_layer(conv2_4,[5,5,64,64],1,'conv2-5') 123 | print('conv2-5') 124 | print(sess.run(tf.shape(conv2_5))) 125 | 126 | # conv2-6 127 | conv2_6 = conv_layer(conv2_5,[5,5,64,64],1,'conv2-6') 128 | print('conv2-6') 129 | print(sess.run(tf.shape(conv2_6))) 130 | 131 | # deconv2_1 132 | deconv2_2 = deconv_layer(conv2_6,[4,4,3,64],[self.batch_size,224,224,3],2,'deconv2-2') 133 | print('deconv2-2') 134 | print(sess.run(tf.shape(deconv2_2))) 135 | 136 | print('finishing a-network') 137 | 138 | tf.summary.image('conv2_1',conv2_1_output[:,:,:,0:3]) 139 | tf.summary.image('conv2_2',conv2_2_output[:,:,:,0:3]) 140 | tf.summary.image('conv2_3',conv2_3[:,:,:,0:3]) 141 | tf.summary.image('conv2_4',conv2_4[:,:,:,0:3]) 142 | tf.summary.image('conv2_5',conv2_5[:,:,:,0:3]) 143 | tf.summary.image('conv2_6',conv2_6[:,:,:,0:3]) 144 | red = tf.reshape(deconv2_2[:,:,:,0], [-1,224,224,1]) 145 | green = tf.reshape(deconv2_2[:,:,:,1], [-1,224,224,1]) 146 | blue = tf.reshape(deconv2_2[:,:,:,2], [-1,224,224,1]) 147 | tf.summary.image('deconv3_1',red) 148 | tf.summary.image('deconv3_1',green) 149 | tf.summary.image('deconv3_1',blue) 150 | #tf.summary.image('deconv2_2-1',deconv2_2[:,:,:,0:1]) 151 | #tf.summary.image('deconv2_2-2',deconv2_2[:,:,:,1:2]) 152 | #tf.summary.image('deconv2_2',deconv2_2[:,:,:,:]) 153 | sess.close() 154 | return deconv2_2 155 | 156 | def S_Net(self,x,G_input,keep_prob): # after conv5 in G_Net 512 157 | 158 | print('making s-network') 159 | sess = tf.Session() 160 | with tf.variable_scope('S_Net'): 161 | # conv3-1 162 | conv3_1 = conv_layer(x,[9,9,3,96],1,'conv3-1') 163 | 164 | # pool5 165 | conv3_1_output = max_pool_layer(conv3_1,[1,3,3,1],2,'pool3-1') 166 | print('conv3-1') 167 | print(sess.run(tf.shape(conv3_1_output))) 168 | 169 | # conv2-2 170 | conv3_2_output = conv_layer(G_input,[1,1,256,64],1,'conv3-2') # need deconv before, also need to change the size of the channel 171 | print('conv3-2') 172 | print(sess.run(tf.shape(conv3_2_output))) 173 | 174 | # concat conv2-1 and conv2-2 175 | conv_concat = tf.concat(axis=3, values = [conv3_1_output,conv3_2_output],name = 'concat_s_net') 176 | 177 | # conv3-3 178 | conv3_3 = conv_layer(conv_concat,[5,5,160,64],1,'conv3-3') 179 | print('conv3-3') 180 | print(sess.run(tf.shape(conv3_3))) 181 | 182 | # conv3-4 183 | conv3_4 = conv_layer(conv3_3,[5,5,64,64],1,'conv3-4') 184 | print('conv3-4') 185 | print(sess.run(tf.shape(conv3_4))) 186 | 187 | # conv3-5 188 | conv3_5 = conv_layer(conv3_4,[5,5,64,64],1,'conv3-5') 189 | print('conv3-5') 190 | print(sess.run(tf.shape(conv3_5))) 191 | 192 | # conv3-6 193 | conv3_6 = conv_layer(conv3_5,[5,5,64,64],1,'conv3-6') 194 | print('conv3-6') 195 | print(sess.run(tf.shape(conv3_6))) 196 | 197 | # deconv3-2 198 | deconv3_2 = deconv_layer(conv3_6,[4,4,3,64],[self.batch_size,224,224,3],2,'decov3-2') 199 | print('decov3-2') 200 | print(sess.run(tf.shape(deconv3_2))) 201 | 202 | 203 | tf.summary.image('conv3_1',conv3_1_output[:,:,:,0:3]) 204 | tf.summary.image('conv3_2',conv3_2_output[:,:,:,0:3]) 205 | tf.summary.image('conv3_3',conv3_3[:,:,:,0:3]) 206 | tf.summary.image('conv3_4',conv3_4[:,:,:,0:3]) 207 | tf.summary.image('conv3_5',conv3_5[:,:,:,0:3]) 208 | tf.summary.image('conv3_6',conv3_6[:,:,:,0:3]) 209 | red = tf.reshape(deconv3_2[:,:,:,0], [-1,224,224,1]) 210 | green = tf.reshape(deconv3_2[:,:,:,1], [-1,224,224,1]) 211 | blue = tf.reshape(deconv3_2[:,:,:,2], [-1,224,224,1]) 212 | tf.summary.image('deconv3_1',red) 213 | tf.summary.image('deconv3_1',green) 214 | tf.summary.image('deconv3_1',blue) 215 | #tf.summary.image('deconv3_2-1',deconv3_2[:,:,:,0:1]) 216 | #tf.summary.image('deconv3_2-2',deconv3_2[:,:,:,1:2]) 217 | #tf.summary.image('deconv3_2',deconv3_2[:,:,:,:]) 218 | print('finishing s-network') 219 | sess.close() 220 | return deconv3_2 221 | 222 | def shadowMatte(self, A_input, S_input): 223 | with tf.variable_scope('F_Matte'): 224 | x = tf.concat([A_input,S_input],3,name='concat_a_s') 225 | x = conv_layer(x,[1,1,6,3],1,'1x1conv') 226 | #x = tf.clip_by_value(x,0,1) 227 | return x 228 | 229 | def loss_function(self, x, ground_truth): 230 | # MSE loss 231 | with tf.variable_scope('Loss'): 232 | #diff = tf.log(tf.clip_by_value(x,1e-10,255)) - tf.log(tf.clip_by_value(ground_truth,1e-10,255)) 233 | diff = tf.log(tf.clip_by_value(x,1e-30,float('Inf'))) - ground_truth 234 | loss = tf.square(diff) 235 | output = tf.reduce_mean(loss) 236 | return output 237 | 238 | def calcShadowImage(self, deshadow, matte): 239 | with tf.variable_scope('Shadow_Img'): 240 | output = tf.multiply(deshadow,matte) 241 | return output 242 | 243 | def calcShadowFreeImage(self, shadow, matte): 244 | with tf.variable_scope('Shadow_Free_Img'): 245 | # log (I_s) = log (S_m) + log (I_ns) 246 | # log(I_ns) = log (I_s) - log (S_m) 247 | #unnorm_shadow = unnorm_image(shadow) 248 | #matte_cliped = tf.clip_by_value(matte, 1e-10,255) 249 | shadow = tf.clip_by_value(shadow,1e-3,255) 250 | log_shadow = tf.log(shadow) 251 | log_shadowfree = log_shadow - matte 252 | #output = tf.divide(shadow,matte) 253 | #output = tf.clip_by_value(output, 0,255) 254 | shadowfree= tf.exp(log_shadowfree) 255 | return tf.clip_by_value(shadowfree, 0,255) 256 | #return unnorm_image(output) 257 | 258 | def calcShadowMatte(self, x, deshadow_image): 259 | with tf.variable_scope('GT_Matte'): 260 | # log (I_s) = log (S_m) + log (I_ns) 261 | # log (S_m) = log (I_s) - log(I_ns) 262 | # but in this case I_s/I_ns cannot be negative or zero 263 | # so what we cannot normalize the input images 264 | # then what happens to the output of network which is normalized? 265 | # matte should be between 0 to 1 266 | x = tf.clip_by_value(x,1e-3,255) 267 | deshadow_image = tf.clip_by_value(deshadow_image,1e-3,255) 268 | log_shadow_matte = tf.log(x) - tf.log(deshadow_image) 269 | log_shadow_matte = tf.clip_by_value(log_shadow_matte,-float('Inf'),tf.log(255.0)) 270 | #return tf.exp(log_shadow_matte) 271 | return log_shadow_matte 272 | def norm_image(x): 273 | with tf.name_scope('norm_vgg_input'): 274 | # Convert RGB to BGR 275 | red, green, blue = tf.split(axis=3, num_or_size_splits=3, value=x) 276 | assert red.get_shape().as_list()[1:] == [224, 224, 1] 277 | assert green.get_shape().as_list()[1:] == [224, 224, 1] 278 | assert blue.get_shape().as_list()[1:] == [224, 224, 1] 279 | bgr = tf.concat(axis=3, values=[ 280 | blue - VGG_MEAN[0], 281 | green - VGG_MEAN[1], 282 | red - VGG_MEAN[2], 283 | ]) 284 | assert bgr.get_shape().as_list()[1:] == [224, 224, 3] 285 | return bgr 286 | 287 | def unnorm_image(x): 288 | with tf.name_scope('unnorm_vgg_input'): 289 | # Convert BGR to RGB 290 | blue, green, red = tf.split(axis=3, num_or_size_splits=3, value=x) 291 | assert red.get_shape().as_list()[1:] == [224, 224, 1] 292 | assert green.get_shape().as_list()[1:] == [224, 224, 1] 293 | assert blue.get_shape().as_list()[1:] == [224, 224, 1] 294 | rgb = tf.concat(axis=3, values=[ 295 | red + VGG_MEAN[2], 296 | green + VGG_MEAN[1], 297 | blue + VGG_MEAN[0], 298 | ]) 299 | assert rgb.get_shape().as_list()[1:] == [224, 224, 3] 300 | return rgb 301 | 302 | def image_show(np_image): 303 | img = Image.fromarray(np_image,'RGB') 304 | img.show() --------------------------------------------------------------------------------