Note (Mac OS): To ensure all dependencies are available set env virable as follows:

    export DYLD_LIBRARY_PATH=/home/user/path_to_CUDNN_folder:$DYLD_LIBRARY_PATH
    export CPATH=/home/user/path_to_CUDNN_folder/include:$CPATH
    export LIBRARY_PATH=/home/user/path_to_CUDNN_folder:$DYLD_LIBRARY_PATH

See details here.


In [1]:
%pylab inline


Populating the interactive namespace from numpy and matplotlib

In [2]:
import lasagne
import numpy as np
import pickle
import skimage.transform
import scipy
import pickle

import theano
import theano.tensor as T

from lasagne.utils import floatX


Using gpu device 0: GeForce GT 750M (CNMeM is disabled)

Memory optimization

Use the following cell if you have any memory issues (generally for old generations of NVIDIA cards, like on GForce 750M with 2G memory)


In [3]:
theano.config.allow_gc = True
theano.config.scan.allow_output_prealloc = False
theano.config.exception_verbosity = 'high'
theano.config.optimizer = 'fast_compile'

VGG-19

Note: in case of low-memory cards use IMAGEWIDTH <= 450


In [4]:
from lasagne.layers import MaxPool2DLayer

Download the normalized pretrained weights from:

https://s3.amazonaws.com/lasagne/recipes/pretrained/imagenet/vgg19_normalized.pkl (original source: https://bethgelab.org/deepneuralart/)

Note: On Mac install wget via homberew. See details here.


In [5]:
!wget -O ../models/googlenet.pkl https://s3.amazonaws.com/lasagne/recipes/pretrained/imagenet/blvc_googlenet.pkl


--2015-11-06 18:25:22--  https://s3.amazonaws.com/lasagne/recipes/pretrained/imagenet/blvc_googlenet.pkl
Resolving s3.amazonaws.com... 54.231.12.144
Connecting to s3.amazonaws.com|54.231.12.144|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 28029725 (27M) [binary/octet-stream]
Saving to: '../models/googlenet.pkl'

../models/googlenet 100%[=====================>]  26.73M   585KB/s   in 42s    

2015-11-06 18:26:04 (659 KB/s) - '../models/googlenet.pkl' saved [28029725/28029725]


In [6]:
IMAGEWIDTH = 600
import googlenet

net = googlenet.build_model(IMAGEWIDTH)

values = pickle.load(open('../models/googlenet.pkl'))['param values']
lasagne.layers.set_all_param_values(net['prob'], [v.astype(np.float32) for v in values])

In [7]:
MEAN_VALUES = np.array([104, 117, 123]).reshape((3,1,1))

def prep_image(im):
    if len(im.shape) == 2:
        im = im[:, :, np.newaxis]
        im = np.repeat(im, 3, axis=2)
    h, w, _ = im.shape
    if h < w:
        im = skimage.transform.resize(im, (IMAGEWIDTH, w*IMAGEWIDTH/h), preserve_range=True)
    else:
        im = skimage.transform.resize(im, (h*IMAGEWIDTH/w, IMAGEWIDTH), preserve_range=True)

    # Central crop
    h, w, _ = im.shape
    im = im[h//2-IMAGEWIDTH//2:h//2+IMAGEWIDTH//2, w//2-IMAGEWIDTH//2:w//2+IMAGEWIDTH//2]
    
    rawim = np.copy(im).astype('uint8')
    
    # Shuffle axes to c01
    im = np.swapaxes(np.swapaxes(im, 1, 2), 0, 1)
    
    # Convert RGB to BGR
    im = im[::-1, :, :]

    im = im - MEAN_VALUES
    return rawim, floatX(im[np.newaxis])

In [8]:
content = imread('../images/content/vasily.jpg')
rawim, content = prep_image(content)
plt.figure(figsize=(8,8))
plt.imshow(rawim)


Out[8]:
<matplotlib.image.AxesImage at 0x11534ecd0>

In [9]:
style = imread('../images/style/Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg')
rawim, style = prep_image(style)
plt.figure(figsize=(8,8))
plt.imshow(rawim)


Out[9]:
<matplotlib.image.AxesImage at 0x11567a410>

In [10]:
def gram_matrix(x):
    x = x.flatten(ndim=3)
    g = T.tensordot(x, x, axes=([2], [2]))
    return g


def content_loss(P, X, layer):
    p = P[layer]
    x = X[layer]
    
    loss = 1./2 * ((x - p)**2).sum()
    return loss


def style_loss(A, X, layer):
    a = A[layer]
    x = X[layer]
    
    A = gram_matrix(a)
    G = gram_matrix(x)
    
    N = a.shape[1]
    M = a.shape[2] * a.shape[3]
    
    loss = 1./(4 * N**2 * M**2) * ((G - A)**2).sum()
    return loss

def total_variation_loss(x):
    return (((x[:,:,:-1,:-1] - x[:,:,1:,:-1])**2 + (x[:,:,:-1,:-1] - x[:,:,:-1,1:])**2)**1.25).sum()

In [11]:
weights = {"content": {"conv2/3x3": 2e-4, "inception_3a/output": 1-2e-4},
            "style": {"conv1/7x7_s2": 0.2, "conv2/3x3": 0.2, "inception_3a/output": 0.2, "inception_4a/output": 0.2,
                      "inception_5a/output": 0.2}}

In [12]:
layers = weights['content'].keys() + weights['style'].keys()
layers = {k: net[k] for k in layers}

In [13]:
# Precompute layer activations for photo and artwork
input_im_theano = T.tensor4()
outputs = lasagne.layers.get_output(layers.values(), input_im_theano)

content_features = {k: theano.shared(output.eval({input_im_theano: content}))
                  for k, output in zip(layers.keys(), outputs)}
style_features = {k: theano.shared(output.eval({input_im_theano: style}))
                for k, output in zip(layers.keys(), outputs)}

In [14]:
# Get expressions for layer activations for generated image
generated_image = theano.shared(floatX(np.random.uniform(-128, 128, (1, 3, IMAGEWIDTH, IMAGEWIDTH))))

gen_features = lasagne.layers.get_output(layers.values(), generated_image)
gen_features = {k: v for k, v in zip(layers.keys(), gen_features)}

In [15]:
# Define loss function
losses = []

# content loss
for layer, weight in weights['content'].iteritems():
    losses.append(weight * content_loss(content_features, gen_features, layer))

# style loss
for layer, weight in weights['style'].iteritems():
    losses.append(weight * style_loss(style_features, gen_features, layer))

# total variation penalty
losses.append(0.1e-7 * total_variation_loss(generated_image))

total_loss = sum(losses)

In [16]:
grad = T.grad(total_loss, generated_image)

In [17]:
# Theano functions to evaluate loss and gradient
f_loss = theano.function([], total_loss)
f_grad = theano.function([], grad)

# Helper functions to interface with scipy.optimize
def eval_loss(x0):
    x0 = floatX(x0.reshape((1, 3, IMAGEWIDTH, IMAGEWIDTH)))
    generated_image.set_value(x0)
    return f_loss().astype('float64')

def eval_grad(x0):
    x0 = floatX(x0.reshape((1, 3, IMAGEWIDTH, IMAGEWIDTH)))
    generated_image.set_value(x0)
    return np.array(f_grad()).flatten().astype('float64')

In [23]:
# Initialize with a noise image
generated_image.set_value(floatX(np.random.uniform(-128, 128, (1, 3, IMAGEWIDTH, IMAGEWIDTH))))

x0 = generated_image.get_value().astype('float64')
xs = []
xs.append(x0)

# Optimize, saving the result periodically
for i in range(8):
    print(i)
    scipy.optimize.fmin_l_bfgs_b(eval_loss, x0.flatten(), fprime=eval_grad, maxfun=40)
    x0 = generated_image.get_value().astype('float64')
    xs.append(x0)


0
1
2
3

In [24]:
def deprocess(x):
    x = np.copy(x[0])
    x += MEAN_VALUES

    x = x[::-1]
    x = np.swapaxes(np.swapaxes(x, 0, 1), 1, 2)
    
    x = np.clip(x, 0, 255).astype('uint8')
    return x

In [25]:
figure(figsize=(12,12))
for i in range(9):
    subplot(3, 3, i+1)
    gca().xaxis.set_visible(False)    
    gca().yaxis.set_visible(False)    
    imshow(deprocess(xs[i]))
tight_layout()


---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-25-1d5e1c62dfa9> in <module>()
      4     gca().xaxis.set_visible(False)
      5     gca().yaxis.set_visible(False)
----> 6     imshow(deprocess(xs[i]))
      7 tight_layout()

IndexError: list index out of range

In [26]:
figure(figsize=(8,8))
imshow(deprocess(xs[-1]), interpolation='nearest')


Out[26]:
<matplotlib.image.AxesImage at 0x116374490>

In [27]:
imsave('../images/result/starry-vasiliy.jpg',deprocess(xs[-1]), )

In [ ]: