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 osascript
’s display notification
:
#!/bin/bash
echo "$@"
osascript -e "display notification \"$@\" with title \"CLI Notification\"" || true
Fun times.