├── .gitignore ├── img-prior-in └── snail.jpg ├── out-denoise ├── noisy-in.png ├── denoised-it000.png ├── denoised-it1000.png ├── denoised-it1500.png ├── denoised-it2000.png ├── denoised-it2500.png ├── denoised-it3000.png ├── denoised-it3500.png ├── denoised-it4000.png ├── denoised-it4500.png ├── denoised-it500.png ├── denoised-it5000.png ├── denoised-it5500.png ├── denoised-it6000.png ├── denoised-it6500.png ├── denoised-it7000.png └── denoised-it7500.png ├── out-inpaint ├── corrupt-in.png ├── output-it000.png ├── output-it1000.png ├── output-it1500.png ├── output-it2000.png ├── output-it2500.png ├── output-it3000.png ├── output-it3500.png └── output-it500.png ├── README.md ├── main-denoise.py └── main-inpaint.py /.gitignore: -------------------------------------------------------------------------------- 1 | sync.sh 2 | -------------------------------------------------------------------------------- /img-prior-in/snail.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/img-prior-in/snail.jpg -------------------------------------------------------------------------------- /out-denoise/noisy-in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/noisy-in.png -------------------------------------------------------------------------------- /out-inpaint/corrupt-in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-inpaint/corrupt-in.png -------------------------------------------------------------------------------- /out-inpaint/output-it000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-inpaint/output-it000.png -------------------------------------------------------------------------------- /out-inpaint/output-it1000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-inpaint/output-it1000.png -------------------------------------------------------------------------------- /out-inpaint/output-it1500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-inpaint/output-it1500.png -------------------------------------------------------------------------------- /out-inpaint/output-it2000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-inpaint/output-it2000.png -------------------------------------------------------------------------------- /out-inpaint/output-it2500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-inpaint/output-it2500.png -------------------------------------------------------------------------------- /out-inpaint/output-it3000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-inpaint/output-it3000.png -------------------------------------------------------------------------------- /out-inpaint/output-it3500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-inpaint/output-it3500.png -------------------------------------------------------------------------------- /out-inpaint/output-it500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-inpaint/output-it500.png -------------------------------------------------------------------------------- /out-denoise/denoised-it000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it000.png -------------------------------------------------------------------------------- /out-denoise/denoised-it1000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it1000.png -------------------------------------------------------------------------------- /out-denoise/denoised-it1500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it1500.png -------------------------------------------------------------------------------- /out-denoise/denoised-it2000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it2000.png -------------------------------------------------------------------------------- /out-denoise/denoised-it2500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it2500.png -------------------------------------------------------------------------------- /out-denoise/denoised-it3000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it3000.png -------------------------------------------------------------------------------- /out-denoise/denoised-it3500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it3500.png -------------------------------------------------------------------------------- /out-denoise/denoised-it4000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it4000.png -------------------------------------------------------------------------------- /out-denoise/denoised-it4500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it4500.png -------------------------------------------------------------------------------- /out-denoise/denoised-it500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it500.png -------------------------------------------------------------------------------- /out-denoise/denoised-it5000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it5000.png -------------------------------------------------------------------------------- /out-denoise/denoised-it5500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it5500.png -------------------------------------------------------------------------------- /out-denoise/denoised-it6000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it6000.png -------------------------------------------------------------------------------- /out-denoise/denoised-it6500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it6500.png -------------------------------------------------------------------------------- /out-denoise/denoised-it7000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it7000.png -------------------------------------------------------------------------------- /out-denoise/denoised-it7500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhengchun/deep-image-prior-tensorflow/HEAD/out-denoise/denoised-it7500.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # deep image prior - tensorflow 2 | A simple yet working implementation of Deep Image Prior paper [https://arxiv.org/pdf/1711.10925.pdf](https://arxiv.org/pdf/1711.10925.pdf) using tensorflow. Free to use/reuse, give me a **star** if you feel it is helpful to you. 3 | 4 | Currently, the denoising and inpainting use cases are implemented. 5 | 6 | #Denoising 7 | remove the image compression artifact. 8 | 9 | Drawing Drawing 10 | 11 | Results after every 1000 iterations, [!] the last one is not always the best one: 12 | 13 | Drawing 14 | Drawing 15 | Drawing 16 | Drawing 17 | Drawing 18 | Drawing 19 | Drawing 20 | Drawing 21 | 22 | # Inpainting 23 | Remove text on image with mask infomation provided. [!] the last one is not always the best one: 24 | 25 | Drawing Drawing 26 | -------------------------------------------------------------------------------- /main-denoise.py: -------------------------------------------------------------------------------- 1 | 2 | ########################################################################## 3 | # https://github.com/lzhengchun/deep-image-prior-tensorflow 4 | # created by Zhengchun Liu at https://lzhengchun.github.io 5 | # free to use / reuse 6 | # just give me a star if you feel it is helpful to you 7 | ########################################################################## 8 | 9 | import tensorflow as tf 10 | import numpy as np 11 | import glob, skimage.measure, skimage.io, imageio, os, shutil, time 12 | 13 | def save2img(d_img, fn): 14 | if len(d_img.shape) == 2: 15 | _min, _max = d_img.min(), d_img.max() 16 | img = (d_img - _min) * 255. / (_max - _min) 17 | else: 18 | img = np.zeros((d_img.shape)) 19 | for c in range(d_img.shape[-1]): 20 | _min, _max = d_img[:, :, c].min(), d_img[:, :, c].max() 21 | img[:, :, c] = (d_img[:, :, c] - _min) * 255. / (_max - _min) 22 | 23 | img = img.astype('uint8') 24 | imageio.imwrite(fn, img) 25 | 26 | def unet_conv_block(inputs, nch): 27 | outputs = tf.layers.conv2d(inputs, nch, 3, padding='same', activation=tf.nn.relu, \ 28 | kernel_initializer=tf.contrib.layers.xavier_initializer()) 29 | 30 | outputs = tf.layers.conv2d(outputs, nch, 3, padding='same', activation=tf.nn.relu, \ 31 | kernel_initializer=tf.contrib.layers.xavier_initializer()) 32 | 33 | return outputs 34 | 35 | def unet_upsample(inputs, nlayers=4): 36 | outputs = {} 37 | outputs[1] = unet_conv_block(inputs, 32) 38 | for layer in range(2, nlayers+1): 39 | _tmp = tf.layers.max_pooling2d(outputs[layer-1], pool_size=2, strides=2, padding='same') 40 | outputs[layer] = unet_conv_block(_tmp, _tmp.shape[-1]*2) 41 | 42 | # intermediate layers 43 | _tmp = tf.layers.max_pooling2d(outputs[nlayers], pool_size=2, strides=2, padding='same') 44 | _tmp = tf.layers.conv2d(_tmp, _tmp.shape[3], 3, padding='same', \ 45 | activation=tf.nn.relu, kernel_initializer=tf.contrib.layers.xavier_initializer()) 46 | for layer, nch in zip(range(1, nlayers+1), (128, 64, 32, 32)): 47 | _tmp = tf.image.resize_images(_tmp, (2*_tmp.shape[1], 2*_tmp.shape[2])) 48 | _tmp = tf.concat([outputs[nlayers-layer+1], _tmp], 3) 49 | _tmp = unet_conv_block(_tmp, nch) 50 | 51 | _tmp = tf.layers.conv2d(_tmp, 16, 1, padding='valid', \ 52 | kernel_initializer=tf.contrib.layers.xavier_initializer(), \ 53 | activation=tf.nn.relu) 54 | _tmp = tf.layers.conv2d(_tmp, inputs.shape[-1], 1, padding='valid', \ 55 | kernel_initializer=tf.contrib.layers.xavier_initializer(), \ 56 | activation=tf.nn.tanh) 57 | return _tmp 58 | 59 | def main(): 60 | it_out_path = 'out' 61 | if os.path.isdir(it_out_path): 62 | shutil.rmtree(it_out_path) 63 | os.mkdir(it_out_path) 64 | 65 | noisy_img = np.expand_dims(skimage.io.imread('img-prior-in/snail.jpg')[2:258]/255. - 1., 0) # norm to [0, 1] 66 | 67 | if len(noisy_img.shape) < 4: noisy_img = np.expand_dims(noisy_img, 3) 68 | img_w, img_h, img_c = noisy_img.shape[1], noisy_img.shape[2], noisy_img.shape[3] 69 | 70 | batch_size = 1 71 | tf.reset_default_graph() 72 | tnsr_img_noisy = tf.placeholder(dtype=tf.float32, shape=[batch_size, img_w, img_h, img_c]) 73 | tnsr_rnd_in = tf.placeholder(dtype=tf.float32, shape=[batch_size, img_w, img_h, img_c]) 74 | with tf.variable_scope('generator') as scope: 75 | img_gen = unet_upsample(tnsr_rnd_in, nlayers=4) 76 | mse_loss= tf.reduce_sum(tf.squared_difference(tnsr_img_noisy, img_gen)) / (np.prod(noisy_img.shape)) 77 | 78 | gen_params = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='generator') 79 | gen_train_op = tf.train.AdamOptimizer().minimize(mse_loss, var_list=gen_params) 80 | 81 | rnd_in = np.random.rand(batch_size, img_w, img_h, img_c) 82 | with tf.Session() as sess: 83 | sess.run(tf.global_variables_initializer()) 84 | for it in xrange(8000): 85 | time_cnt = time.time() 86 | _img_gen, _mse_loss, _ = sess.run([img_gen, mse_loss, gen_train_op], feed_dict={tnsr_rnd_in:rnd_in, tnsr_img_noisy:noisy_img}) 87 | 88 | if it % 500 == 0: 89 | save2img(_img_gen[0], "%s/denoised-it%03d.png" % (it_out_path, it)) 90 | if it==0: save2img(noisy_img[0], "%s/noisy-in.png" % (it_out_path, )) 91 | print "it:%03d, mse-loss:%.3f, it_Telapse: %.3fs" % (it, _mse_loss, time.time() - time_cnt) 92 | 93 | if __name__ == '__main__': 94 | os.environ['CUDA_VISIBLE_DEVICES'] = '0' 95 | main() 96 | -------------------------------------------------------------------------------- /main-inpaint.py: -------------------------------------------------------------------------------- 1 | 2 | import tensorflow as tf 3 | import numpy as np 4 | import glob, skimage.measure, skimage.io, imageio, os, shutil, time 5 | 6 | def save2img(d_img, fn): 7 | if len(d_img.shape) == 2: 8 | _min, _max = d_img.min(), d_img.max() 9 | img = (d_img - _min) * 255. / (_max - _min) 10 | else: 11 | img = np.zeros((d_img.shape)) 12 | for c in range(d_img.shape[-1]): 13 | _min, _max = d_img[:, :, c].min(), d_img[:, :, c].max() 14 | img[:, :, c] = (d_img[:, :, c] - _min) * 255. / (_max - _min) 15 | 16 | img = img.astype('uint8') 17 | imageio.imwrite(fn, img) 18 | 19 | def unet_conv_block(inputs, nch): 20 | outputs = tf.layers.conv2d(inputs, nch, 3, padding='same', activation=tf.nn.relu, \ 21 | kernel_initializer=tf.contrib.layers.xavier_initializer()) 22 | 23 | outputs = tf.layers.conv2d(outputs, nch, 3, padding='same', activation=tf.nn.relu, \ 24 | kernel_initializer=tf.contrib.layers.xavier_initializer()) 25 | 26 | return outputs 27 | 28 | def unet_upsample(inputs, nlayers=4): 29 | outputs = {} 30 | outputs[1] = unet_conv_block(inputs, 32) 31 | for layer in range(2, nlayers+1): 32 | _tmp = tf.layers.max_pooling2d(outputs[layer-1], pool_size=2, strides=2, padding='same') 33 | outputs[layer] = unet_conv_block(_tmp, _tmp.shape[-1]*2) 34 | 35 | # intermediate layers 36 | _tmp = tf.layers.max_pooling2d(outputs[nlayers], pool_size=2, strides=2, padding='same') 37 | _tmp = tf.layers.conv2d(_tmp, _tmp.shape[3], 3, padding='same', \ 38 | activation=tf.nn.relu, kernel_initializer=tf.contrib.layers.xavier_initializer()) 39 | for layer, nch in zip(range(1, nlayers+1), (128, 64, 32, 32)): 40 | _tmp = tf.image.resize_images(_tmp, (2*_tmp.shape[1], 2*_tmp.shape[2])) 41 | _tmp = tf.concat([outputs[nlayers-layer+1], _tmp], 3) 42 | _tmp = unet_conv_block(_tmp, nch) 43 | 44 | _tmp = tf.layers.conv2d(_tmp, 16, 1, padding='valid', \ 45 | kernel_initializer=tf.contrib.layers.xavier_initializer(), \ 46 | activation=tf.nn.relu) 47 | _tmp = tf.layers.conv2d(_tmp, inputs.shape[-1], 1, padding='valid', \ 48 | kernel_initializer=tf.contrib.layers.xavier_initializer(), \ 49 | activation=tf.nn.tanh) 50 | return _tmp 51 | 52 | def main(): 53 | it_out_path = 'out' 54 | if os.path.isdir(it_out_path): 55 | shutil.rmtree(it_out_path) 56 | os.mkdir(it_out_path) 57 | 58 | img_ori = skimage.io.imread('img-prior-in/kate.png') 59 | img_msk = skimage.io.imread('img-prior-in/kate_mask.png') / 255 60 | img_cor = np.expand_dims(img_ori * np.expand_dims(img_msk, 2), 0) / 255. - 1. 61 | 62 | msk_in = np.expand_dims(np.array([img_msk, img_msk, img_msk]).transpose((1, 2, 0)), 0) 63 | 64 | if len(img_cor.shape) < 4: img_cor = np.expand_dims(img_cor, 3) 65 | img_w, img_h, img_c = img_cor.shape[1], img_cor.shape[2], img_cor.shape[3] 66 | 67 | batch_size = 1 68 | tf.reset_default_graph() 69 | tnsr_img_cor = tf.placeholder(dtype=tf.float32, shape=[batch_size, img_w, img_h, img_c]) 70 | tnsr_img_msk = tf.placeholder(dtype=tf.float32, shape=[batch_size, img_w, img_h, img_c]) 71 | tnsr_rnd_in = tf.placeholder(dtype=tf.float32, shape=[batch_size, img_w, img_h, img_c]) 72 | with tf.variable_scope('generator') as scope: 73 | img_gen = unet_upsample(tnsr_rnd_in, nlayers=4) 74 | 75 | mse_loss= tf.reduce_mean(tf.squared_difference(tnsr_img_cor, img_gen * tnsr_img_msk)) 76 | 77 | gen_params = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='generator') 78 | gen_train_op = tf.train.AdamOptimizer().minimize(mse_loss, var_list=gen_params) 79 | 80 | rnd_in = np.random.rand(batch_size, img_w, img_h, img_c) 81 | with tf.Session() as sess: 82 | sess.run(tf.global_variables_initializer()) 83 | for it in xrange(4000): 84 | time_cnt = time.time() 85 | _img_gen, _mse_loss, _ = sess.run([img_gen, mse_loss, gen_train_op], \ 86 | feed_dict={tnsr_rnd_in: rnd_in, tnsr_img_cor: img_cor, \ 87 | tnsr_img_msk: msk_in}) 88 | 89 | if it % 500 == 0: 90 | save2img(_img_gen[0], "%s/output-it%03d.png" % (it_out_path, it)) 91 | if it==0: save2img(img_cor[0], "%s/noisy-in.png" % (it_out_path, )) 92 | print "it:%03d, mse-loss:%.3f, it_Telapse: %.3fs" % (it, _mse_loss, time.time() - time_cnt) 93 | 94 | if __name__ == '__main__': 95 | os.environ['CUDA_VISIBLE_DEVICES'] = '0' 96 | main() 97 | --------------------------------------------------------------------------------