"""DeepDream — the original 2015 Inceptionism, faithfully in PyTorch on ZeroGPU. A port of Alexander Mordvintsev's dream.ipynb: normalized gradient ascent on GoogLeNet layers across octaves, guided dreams, and the endless "dream zoom". Uses the original BVLC caffe weights (and Places365) hosted at mediasynthesismuseum/deepdream-googlenet. """ import os os.environ.setdefault("PYTORCH_CUDA_ALLOC_CONF", "expandable_segments:True") import spaces # before torch import numpy as np import torch import gradio as gr import imageio.v2 as imageio from PIL import Image from huggingface_hub import hf_hub_download import dreamer from dd_models import BVLC_GOOGLENET, GoogLeNetPlaces REPO = "mediasynthesismuseum/deepdream-googlenet" def _load(cls, filename): net = cls() net.add_layers() sd = torch.load(hf_hub_download(REPO, filename), map_location="cpu", weights_only=False) msd = net.state_dict() net.load_state_dict({k: v for k, v in sd.items() if k in msd and v.shape == msd[k].shape}, strict=False) net.eval().to("cuda") for p in net.parameters(): p.requires_grad_(False) return net MODELS = { "ImageNet — dogs, eyes, pagodas (the classic)": _load(BVLC_GOOGLENET, "bvlc_googlenet.pth"), "Places365 — buildings, domes, landscapes": _load(GoogLeNetPlaces, "googlenet_places365.pth"), } LAYERS = { "3b/output — edges & textures (impressionist)": "inception_3b_output", "4c/output — balanced (classic default)": "inception_4c_output", "4d/output — richer shapes": "inception_4d_output", "4e/output — big objects": "inception_4e_output", "5b/output — high-level features": "inception_5b_output", "3b/5x5_reduce — fine filigree": "inception_3b_5x5_reduce", } def _prep(img, max_side): im = Image.fromarray(img).convert("RGB") if isinstance(img, np.ndarray) else img.convert("RGB") w, h = im.size s = max_side / max(w, h) if s < 1: im = im.resize((max(1, int(w * s)), max(1, int(h * s))), Image.LANCZOS) return np.float32(im) @spaces.GPU(duration=90) def run_dream(image, model_name, layer_label, size, iters, octaves, octave_scale, step, jitter, guide): if image is None: raise gr.Error("Upload an image first.") net = MODELS[model_name] base = _prep(image, int(size)) guide_rgb = _prep(guide, min(int(size), 448)) if guide is not None else None last = None for oi, on, im in dreamer.deepdream(net, base, layer=LAYERS[layer_label], iter_n=int(iters), octave_n=int(octaves), octave_scale=float(octave_scale), step=float(step), jitter=int(jitter), guide_rgb=guide_rgb): last = im yield im, f"octave {oi}/{on} — dreaming…" yield last, "✨ done" def _zoom_dur(image, model_name, layer_label, size, iters, octaves, frames, zoom): return min(300, 15 + int(frames) * 4) @spaces.GPU(duration=_zoom_dur) def run_zoom(image, model_name, layer_label, size, iters, octaves, frames, zoom): if image is None: raise gr.Error("Upload an image first.") net = MODELS[model_name] layer = LAYERS[layer_label] frame = _prep(image, int(size)) h, w = frame.shape[:2] out = [] for i in range(int(frames)): frame = dreamer.dream_once(net, frame, layer=layer, iter_n=int(iters), octave_n=int(octaves), step=1.5, jitter=32) out.append(np.uint8(frame)) yield np.uint8(frame), None, f"frame {i + 1}/{int(frames)} — into the dream…" # zoom in: scale up then centre-crop back (the notebook's affine feedback) z = 1.0 + float(zoom) big = Image.fromarray(np.uint8(frame)).resize((int(w * z), int(h * z)), Image.LANCZOS) left, top = (big.width - w) // 2, (big.height - h) // 2 frame = np.float32(big.crop((left, top, left + w, top + h))) path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "dream_zoom.mp4") imageio.mimsave(path, out, fps=12, quality=8) yield out[-1], path, "✨ done" CSS = """ .gradio-container { max-width: 1120px !important; margin: 0 auto !important; } .dark .gradio-container { color: var(--body-text-color); } #dd-title { text-align: center; } """ with gr.Blocks(title="DeepDream") as demo: gr.Markdown( "# 🌀 DeepDream\n" "The original 2015 *Inceptionism* — [Mordvintsev's `dream.ipynb`](https://github.com/google/deepdream), " "faithfully in PyTorch on ZeroGPU with the " "[original caffe weights](https://huggingface.co/mediasynthesismuseum/deepdream-googlenet).", elem_id="dd-title", ) with gr.Row(): with gr.Column(scale=5): # controls + button (left) image = gr.Image(label="Input image", type="numpy", height=260) with gr.Row(): model = gr.Dropdown(list(MODELS), value=list(MODELS)[0], label="Model") layer = gr.Dropdown(list(LAYERS), value=list(LAYERS)[1], label="Layer (what it dreams)") size = gr.Slider(256, 1024, 600, step=32, label="Size") with gr.Accordion("Advanced", open=False): with gr.Row(): iters = gr.Slider(1, 40, 10, step=1, label="Iterations / octave") octaves = gr.Slider(1, 8, 4, step=1, label="Octaves") octave_scale = gr.Slider(1.1, 1.8, 1.4, step=0.05, label="Octave scale") with gr.Row(): step = gr.Slider(0.5, 4.0, 1.5, step=0.1, label="Step size") jitter = gr.Slider(0, 64, 32, step=1, label="Jitter") with gr.Tabs(): with gr.Tab("Dream"): with gr.Accordion("Guided dream (optional)", open=False): guide = gr.Image(label="Guide image — dreams in its style", type="numpy", height=150) dream_btn = gr.Button("🌀 Dream", variant="primary") with gr.Tab("Dream Zoom"): with gr.Row(): frames = gr.Slider(4, 60, 20, step=1, label="Frames") zoom = gr.Slider(0.01, 0.15, 0.05, step=0.01, label="Zoom / frame") zoom_btn = gr.Button("🎞️ Dream Zoom", variant="primary") with gr.Column(scale=6): # output + status (right) dream_out = gr.Image(label="Dream", height=460) zoom_out = gr.Video(label="Dream zoom", autoplay=True, loop=True, visible=False) zoom_frame = gr.Image(label="Current frame", height=220, visible=False) status = gr.Textbox(label="Status", interactive=False) dream_btn.click( lambda: (gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)), None, [dream_out, zoom_out, zoom_frame]).then( run_dream, [image, model, layer, size, iters, octaves, octave_scale, step, jitter, guide], [dream_out, status]) zoom_btn.click( lambda: (gr.update(visible=False), gr.update(visible=True), gr.update(visible=True)), None, [dream_out, zoom_out, zoom_frame]).then( run_zoom, [image, model, layer, size, iters, octaves, frames, zoom], [zoom_frame, zoom_out, status]) gr.Examples([["examples/sky.jpg"], ["examples/dog.jpg"]], inputs=image) if __name__ == "__main__": demo.queue().launch(theme=gr.themes.Citrus(), css=CSS)