├── Vagrantfile ├── README.md └── dreamify.py /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure(2) do |config| 5 | config.vm.box = "data-science-toolbox/dst" 6 | 7 | # Salt to taste 8 | config.vm.provider "virtualbox" do |v| 9 | v.memory = 2048 10 | v.cpus = 4 11 | end 12 | 13 | config.vm.provision "shell", inline: <<-SHELL 14 | sudo apt-get update 15 | sudo apt-get install -y git bc wget 16 | sudo apt-get install -y libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libboost-all-dev libhdf5-serial-dev 17 | sudo apt-get install -y libgflags-dev libgoogle-glog-dev liblmdb-dev protobuf-compiler 18 | sudo apt-get install -y libopenblas-base libopenblas-dev 19 | git clone https://github.com/BVLC/caffe.git 20 | cd caffe 21 | cp Makefile.config.example Makefile.config 22 | sed -i "s/# CPU_ONLY := 1/CPU_ONLY := 1/" Makefile.config 23 | sed -i "s/BLAS := atlas/BLAS := open/" Makefile.config 24 | make -j`nproc` all 25 | 26 | # Uncomment the below if you're feeling paranoid. We're not running in production or anything, here. 27 | # make -j`nproc` test 28 | # make -j`nproc` runtest 29 | 30 | make -j`nproc` pycaffe 31 | for req in $(cat python/requirements.txt); do sudo pip install $req; done 32 | echo 'export PYTHONPATH=/home/vagrant/caffe/python:$PYTHONPATH' >> /home/vagrant/.profile 33 | if [ ! -f "/home/vagrant/caffe/models/bvlc_googlenet/bvlc_googlenet.caffemodel" ]; then 34 | wget -q http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel -O /home/vagrant/caffe/models/bvlc_googlenet/bvlc_googlenet.caffemodel 35 | fi 36 | SHELL 37 | end 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # image-dreamer 2 | "Dreams" images, such as shown in the [Google Research blog post on "Inceptionism"](http://googleresearch.blogspot.ch/2015/06/inceptionism-going-deeper-into-neural.html). 3 | 4 | ## What's it do? 5 | Using a deep neural network, it turns images like this: 6 | 7 | ![](https://cloud.githubusercontent.com/assets/235769/8487629/318827be-20c2-11e5-9b3a-ec15b0871a4d.jpg) 8 | 9 | Into this: 10 | 11 | ![](https://cloud.githubusercontent.com/assets/235769/8487642/3f91eb74-20c2-11e5-87aa-87ed27236f22.png) 12 | 13 | Read the [Google Research blog post on "Inceptionism"](http://googleresearch.blogspot.ch/2015/06/inceptionism-going-deeper-into-neural.html) to learn more about how it works. 14 | 15 | ## Installation 16 | * Install [Vagrant](https://www.vagrantup.com/) 17 | * Clone this repo 18 | * `cd image-dreamer` 19 | * `vagrant up` 20 | * Go grab a coffee, this will take a while 21 | 22 | ## Usage 23 | * Copy any JPEG images you want to "dreamify" into the `image-dreamer` directory 24 | * `vagrant ssh` 25 | * `cd /vagrant` 26 | * `ipython dreamify.py ` 27 | * Freak out! 28 | 29 | ## Credits 30 | Thanks to the great work of Google's [deepdream](https://github.com/google/deepdream/blob/master/dream.ipynb) team! 31 | 32 | The Vagrant file and Vagrantbox are based on those provided by [Data Science Toolbox](http://datasciencetoolbox.org/). Big thanks to them for providing the scientific Python bootstrap I needed to get this going! 33 | 34 | ## Contributing 35 | Have fun, hack, contribute! This is just a starting point, I'd love to see where people take this! 36 | 37 | If you make changes, please consider issuing a pull request. I'm happy to oblige. 38 | 39 | Thanks to @borzoj and @dirtyvader for their contributions! 40 | -------------------------------------------------------------------------------- /dreamify.py: -------------------------------------------------------------------------------- 1 | # imports and basic notebook setup 2 | from cStringIO import StringIO 3 | import numpy as np 4 | import scipy.ndimage as nd 5 | import PIL.Image 6 | from IPython.display import clear_output, Image, display 7 | from google.protobuf import text_format 8 | 9 | import caffe 10 | 11 | import sys 12 | 13 | def savearray(a, filename, fmt='png'): 14 | a = np.uint8(np.clip(a, 0, 255)) 15 | with open(filename, 'wb') as f: 16 | PIL.Image.fromarray(a).save(f, fmt) 17 | #display(Image(data=f.getvalue())) 18 | 19 | model_path = '/home/vagrant/caffe/models/bvlc_googlenet/' # substitute your path here 20 | net_fn = model_path + 'deploy.prototxt' 21 | param_fn = model_path + 'bvlc_googlenet.caffemodel' 22 | 23 | # Patching model to be able to compute gradients. 24 | # Note that you can also manually add "force_backward: true" line to "deploy.prototxt". 25 | model = caffe.io.caffe_pb2.NetParameter() 26 | text_format.Merge(open(net_fn).read(), model) 27 | model.force_backward = True 28 | open('tmp.prototxt', 'w').write(str(model)) 29 | 30 | net = caffe.Classifier('tmp.prototxt', param_fn, 31 | mean = np.float32([104.0, 116.0, 122.0]), # ImageNet mean, training set dependent 32 | channel_swap = (2,1,0)) # the reference model has channels in BGR order instead of RGB 33 | 34 | # a couple of utility functions for converting to and from Caffe's input image layout 35 | def preprocess(net, img): 36 | return np.float32(np.rollaxis(img, 2)[::-1]) - net.transformer.mean['data'] 37 | def deprocess(net, img): 38 | return np.dstack((img + net.transformer.mean['data'])[::-1]) 39 | 40 | def make_step(net, step_size=1.5, end='inception_4c/output', jitter=32, clip=True): 41 | '''Basic gradient ascent step.''' 42 | 43 | src = net.blobs['data'] # input image is stored in Net's 'data' blob 44 | dst = net.blobs[end] 45 | 46 | ox, oy = np.random.randint(-jitter, jitter+1, 2) 47 | src.data[0] = np.roll(np.roll(src.data[0], ox, -1), oy, -2) # apply jitter shift 48 | 49 | net.forward(end=end) 50 | dst.diff[:] = dst.data # specify the optimization objective 51 | net.backward(start=end) 52 | g = src.diff[0] 53 | # apply normalized ascent step to the input image 54 | src.data[:] += step_size/np.abs(g).mean() * g 55 | 56 | src.data[0] = np.roll(np.roll(src.data[0], -ox, -1), -oy, -2) # unshift image 57 | 58 | if clip: 59 | bias = net.transformer.mean['data'] 60 | src.data[:] = np.clip(src.data, -bias, 255-bias) 61 | 62 | def deepdream(net, base_img, iter_n=10, octave_n=4, octave_scale=1.4, end='inception_4c/output', clip=True, **step_params): 63 | # prepare base images for all octaves 64 | octaves = [preprocess(net, base_img)] 65 | for i in xrange(octave_n-1): 66 | octaves.append(nd.zoom(octaves[-1], (1, 1.0/octave_scale,1.0/octave_scale), order=1)) 67 | 68 | src = net.blobs['data'] 69 | detail = np.zeros_like(octaves[-1]) # allocate image for network-produced details 70 | for octave, octave_base in enumerate(octaves[::-1]): 71 | h, w = octave_base.shape[-2:] 72 | if octave > 0: 73 | # upscale details from the previous octave 74 | h1, w1 = detail.shape[-2:] 75 | detail = nd.zoom(detail, (1, 1.0*h/h1,1.0*w/w1), order=1) 76 | 77 | src.reshape(1,3,h,w) # resize the network's input image size 78 | src.data[0] = octave_base+detail 79 | for i in xrange(iter_n): 80 | make_step(net, end=end, clip=clip, **step_params) 81 | 82 | # visualization 83 | vis = deprocess(net, src.data[0]) 84 | if not clip: # adjust image contrast if clipping is disabled 85 | vis = vis*(255.0/np.percentile(vis, 99.98)) 86 | #showarray(vis) 87 | print octave, i, end, vis.shape 88 | clear_output(wait=True) 89 | 90 | # extract details produced on the current octave 91 | detail = src.data[0]-octave_base 92 | # returning the resulting image 93 | return deprocess(net, src.data[0]) 94 | 95 | if 'keys'==sys.argv[1]: 96 | print "\n".join( net.blobs.keys()) 97 | sys.exit(0) 98 | 99 | img = np.float32(PIL.Image.open(sys.argv[1])) 100 | end_name = sys.argv[3] if len(sys.argv)>3 else 'inception_4c/output' 101 | iter_n = int(sys.argv[4]) if len(sys.argv)>4 else 10 102 | octaves = int(sys.argv[5]) if len(sys.argv)>5 else 4 103 | oct_scale = float(sys.argv[6]) if len(sys.argv)>6 else 1.4 104 | _=deepdream(net, img, end=end_name, iter_n=iter_n, octave_n=octaves, octave_scale=oct_scale) 105 | savearray(_, sys.argv[2]) 106 | --------------------------------------------------------------------------------