├── .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 |
10 |
11 | Results after every 1000 iterations, [!] the last one is not always the best one:
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | # Inpainting
23 | Remove text on image with mask infomation provided. [!] the last one is not always the best one:
24 |
25 |
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 |
--------------------------------------------------------------------------------