DeepDream is a research project originally from Google that gives you a look into how neural networks see the world. They’re fascinating, bizarre, and a lot of fun to play with. A bit of work getting them to work on your own machine though.
Luckily, GitHub user saturnism has put together a lovely Docker-based tool that will do just that for us: deepdream-cli-docker. Unfortunately, the commands are still a bit long. Let’s clean it up a bit and add the ability to dream about non-JPGs (animated GIFs especially!).
Base case: JPGs
First, we want the base case. How do we convert a jpg?
cat $filename | docker run -i saturnism/deepdream-cli -l inception_4b/output > dream-$filename ^ /dev/null
That’s easy enough. Put that as an alias and it works for just about any Bash-ish shell.
><> open hello-frame.jpg
><> dream hello-frame.jpg I'm dreaming of hello-frame.jpg... Working in /tmp/dream.nJTQ hello-frame.jpg has awoken ><> open dream-hello-frame.jpg
Let’s go deeper.
><> begin for i in (seq 1 10) dream hello-frame.jpg mv dream-hello-frame.jpg hello-frame.jpg end mv hello-frame.jpg inception-dream-hello-frame.jpg end I'm dreaming of hello-frame.jpg... Working in /tmp/dream.hWOx hello-frame.jpg has awoken ... I'm dreaming of hello-frame.jpg... Working in /tmp/dream.iA6i hello-frame.jpg has awoken ><> open inception-dream-hello-frame.jpg
Non-JPGs: Convert and dream
Next, let’s expand that a bit to any single frame, non-JPG format. ImageMagick to the rescue:
convert $filename $filename.jpg cat $filename.jpg | docker run -i saturnism/deepdream-cli -l inception_4b/output > dream-$filename.jpg ^ /dev/null convert dream-$filename.jpg dream-$filename
Dream deeper: Converting GIFs frame by frame
Okay, let’s get a bit more interesting now. What if want to apply a Deep Dream to an entire GIF one frame at a time:
mkdir src-frames dst-frames convert $filename -coalesce src-frames/%04d.jpg set -lx framecount (ls src-frames | wc -l) for f in (ls src-frames/) cat src-frames/$f | docker run -i saturnism/deepdream-cli -l inception_4b/output > dst-frames/$f ^ /dev/null echo "$filename: Rendered $f (of $framecount)" end convert dst-frames/* -set delay 0 -strip -coalesce -layers Optimize dream-$filename
This one I particularly like. Essentially, we have three parts. Converting a GIF to JPG will automatically unpack each frame to its own image. We need the
-coalesce option, otherwise transparent parts of frames (where they are just relying on the previous frame’s color) will just end up with a solid color. The
%04d.jpg makes sure that the frame filenames have leading zeros so they will sort properly.
Then, we convert each frame one at a time and put them all back together, optimizing as we go. Pretty cool that.
><> open hello.gif
><> dream hello.gif I'm dreaming of hello.gif... Working in /tmp/dream.MrBg hello.gif: Rendered 0000.jpg (of 51) hello.gif: Rendered 0001.jpg (of 51) hello.gif: Rendered 0002.jpg (of 51) hello.gif: Rendered 0049.jpg (of 51) hello.gif: Rendered 0050.jpg (of 51) hello.gif: Rendered 0051.jpg (of 51) hello.gif has awoken! ><> open dream-hello.gif
Finally, we want to wrap up everything. Specifically, we want:
- Allow multiple files to be converted at once
- Use a temporary folder and clean up when we’re done
- Print out a bit more progress as we go
We can wrap this all up fairly cleanly:
for filename in $argv notify "I'm dreaming of $filename..." set -lx tmpdir (mktemp -d /tmp/dream.XXXX) cp $filename $tmpdir pushd $tmpdir echo "Working in $tmpdir" if test (string match -r ".gif" $filename) # GIF conversion else if test (string match -r ".jpg" $filename) # JPG conversion else # ANYTHING ELSE end popd mv $tmpdir/dream-$filename . rm -rf $tmpdir notify "$filename has awoken" end
I like working with temporary directories with
mktemp, it’s handy.
notify is another custom dotfile I have that will always echo, but on OSX will also display a notification using
#!/bin/bash echo "$@" osascript -e "display notification \"$@\" with title \"CLI Notification\"" || true