Visual Anagrams: making one image look like two under rotation
Code for the paper "Visual Anagrams: Generating Multi-View Optical Illusions with Diffusion Models"
At a glance
- What is it?
- Visual Anagrams is the code for a CVPR 2024 paper that generates multi-view optical illusions with a diffusion model, so a single picture changes identity when it is rotated or inverted. It suits a researcher reproducing the paper or experimenting with multi-view generation, and it needs DeepFloyd IF access rather than Stable Diffusion.
- Who is it for?
- Adopt this repository if you want to reproduce the Visual Anagrams paper or experiment with multi-view generation, since it ships the generation, upscaling and animation scripts with a two-tier Colab notebook so you can try it without a local GPU. Do not adapt the approach to Stable Diffusion, because the README states latent diffusion models cause artifacts in illusions, which is why DeepFloyd IF is used instead.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 100 days ago.
- What is it written in?
- Mainly Jupyter Notebook, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One image, two readings, one transform
Visual Anagrams is the code for the paper Visual Anagrams: Generating Multi-View Optical Illusions with Diffusion Models, published at CVPR 2024 as an oral, by Daniel Geng, Aaron Park and Andrew Owens. The project site is at dangeng.github.io/visual_anagrams/ and the arXiv entry is 2311.17919.
The idea is stated in one paragraph. The repository contains code to generate visual anagrams and other multi-view optical illusions, which are images that change appearance or identity when transformed, such as by a rotation, a colour inversion, or a jigsaw rearrangement. The README points you to the paper or the website for the details.
The composition is the hard part. You are asking a diffusion model for a single image that simultaneously reads as a village when viewed one way and as a horse when rotated, which is a joint constraint rather than two separate generations stitched together. That is why the method is a research contribution and not a prompt trick, and it is why the code, rather than a prompt, is what the repository contains.
The repository also carries a second project. The note at the top says the repo contains code for both Visual Anagrams and Factorized Diffusion, and points to a separate readme for the factorized diffusion information.
The primary language is listed as Jupyter Notebook, the licence is MIT, and the last push to the main branch was on 2026-07-17 with no GitHub releases.
DeepFloyd IF, and why not Stable Diffusion
The installation section starts with a decision that shapes everything, and the reasoning is worth quoting because it is the opposite of the usual default.
The method uses DeepFloyd IF, a pixel-based diffusion model, and the README states plainly that Stable Diffusion is not used because latent diffusion models cause artifacts in illusions.
That is a specific technical constraint rather than a preference. The illusion has to hold across the transform, and a latent diffusion pipeline compresses to a low dimensional latent space and decodes back, which introduces errors that show up differently in each view. Working in pixel space avoids the compression entirely, at the cost of a much bigger model and a much smaller output resolution.
The access requirements are the practical hurdle. Before using DeepFloyd IF you must accept its usage conditions, and the steps are: make sure you have a Hugging Face account and are logged in, accept the license on the model card of DeepFloyd/IF-I-XL-v1.0, where accepting the licence on the stage I model card auto accepts for the other IF models, and then log in locally by running:
python huggingface_login.pyand entering your Hugging Face Hub access token when prompted. The README adds that it does not matter how you answer the Add token as git credential question.
The environment itself is a conda environment, created only on Linux:
conda env create -f environment.ymland then activated with:
conda activate visual_anagramsThe Linux-only note matters, because the Colab route is the other way in and it needs no local setup at all.
Generating a rotation illusion from the command line
The usage section gives one command that produces most of what you need, and unpacking its arguments tells you the shape of the whole system.
python generate.py --name rotate_cw.village.horse --prompts "a snowy mountain village" "a horse" --style "an oil painting of" --views identity rotate_cw --num_samples 10 --num_inference_steps 30 --guidance_scale 10.0 --generate_1024This creates 10 samples at 3 different sizes, 64 by 64, 256 by 256 and 1024 by 1024.
The arguments describe the two views. The name is the illusion name and samples are saved to ./results/{name}, which is why it carries both the transformation and the two subjects. The prompts are a list of prompts for the illusions, one per view. The style is an optional style prompt prepended to each of the prompts, for example an oil painting of, and the README notes it saves some writing. The views are a list of views to use, and it must match the number of prompts, with the list of available views in the get_views function in visual_anagrams/views/__init__.py.
The generation parameters are conventional diffusion ones with different names. num_samples is the number of illusions to sample, num_inference_steps is the number of diffusion denoising steps to take, and guidance_scale is the guidance scale for classifier free guidance.
The final flag is the one with a subtlety. --generate_1024 uses DeepFloyd Stage III, which the README notes is just the Stable Diffusion 4x Upscaler, to upsample to 1024 by 1024. The upscaling section explains why that is a separate stage: the first two stages of DeepFloyd IF generate the 64 and 256 multi-view illusion, and the upscaler model uses latents, so multi-view denoising could not be implemented for it, so it can only naively upsample using just the first prompt. The README concedes this may affect the quality of transformed images but says in practice it works quite well.
Animating the illusion, and the prompt advice that comes with it
Once you have the images, a second script turns the pair into an animation.
python animate.py --im_path results/rotate_cw.village.horse/0000/sample_1024.png --metadata_path results/rotate_cw.village.horse/metadata.pklThe command works for all three sampled sizes, 64, 256 and 1024, though the README admits 64 by 64 is very small and looks quite bad. The metadata path is the path to metadata about the views and prompts used to generate the illusion, which is saved by generate.py, and it overrides the options below.
Those options are the view name, taken from the same get_views function, and two prompts. prompt_1 is the prompt for the original image, and you can add newline characters there for line breaks, and prompt_2 is the same but for the transformed image. So the animation script can also be driven manually, but the metadata route reuses what the generation step already recorded.
The closing section of the README is the most practically useful part, because it is advice on how to choose prompts for illusions, and the advice is mostly a warning against over-confidence.
The first tip is that intuition and reasoning works less often than you would expect. Prompts you think would work great often work poorly and vice versa, so exploration is key. The second notes that styles such as a photo of tend to be harder, because the constraint of realism is fairly difficult to satisfy.
That is an unusually candid statement for a research code release, and it is a signal about the method. If the results depended on reasoning about what would work, the project would not need a section telling you that reasoning does not help. It is telling you to sample widely and look, which is the opposite of how prompt engineering advice usually reads, and it matches the example command above, which asks for ten samples.
Editorial conclusion
Adopt this repository if you want to reproduce the Visual Anagrams paper or experiment with multi-view generation, since it ships the generation, upscaling and animation scripts with a two-tier Colab notebook so you can try it without a local GPU. Do not adapt the approach to Stable Diffusion, because the README states latent diffusion models cause artifacts in illusions, which is why DeepFloyd IF is used instead. Before you start, accept the DeepFloyd IF licence on the Hugging Face model card and log in with a Hub token, and read the prompt advice section, because the author is candid that intuition about which prompts will work is unreliable and exploration matters more than reasoning.
Frequently asked questions
What does Visual Anagrams generate?
It generates visual anagrams and other multi-view optical illusions, which are images that change appearance or identity when transformed, such as by a rotation, a colour inversion or a jigsaw rearrangement. The method generates a single image that reads as one subject in one view and another subject in the transformed view, and the code is from the CVPR 2024 oral paper by Daniel Geng, Aaron Park and Andrew Owens.
Why does Visual Anagrams use DeepFloyd IF instead of Stable Diffusion?
The README states that the method uses DeepFloyd IF, a pixel-based diffusion model, and that Stable Diffusion is not used because latent diffusion models cause artifacts in illusions. Using DeepFloyd IF also requires accepting the licence on the DeepFloyd/IF-I-XL-v1.0 model card and logging in locally with a Hugging Face Hub access token.
How do I generate a rotation illusion with Visual Anagrams?
Run `python generate.py --name rotate_cw.village.horse --prompts "a snowy mountain village" "a horse" --style "an oil painting of" --views identity rotate_cw --num_samples 10 --num_inference_steps 30 --guidance_scale 10.0 --generate_1024`, which creates 10 samples at 64, 256 and 1024 pixels. The number of views must match the number of prompts, and the available views are in the get_views function.
How do I animate a Visual Anagrams illusion?
Run `python animate.py --im_path results/rotate_cw.village.horse/0000/sample_1024.png --metadata_path results/rotate_cw.village.horse/metadata.pkl`. The metadata file, saved by generate.py, records the views and prompts used and overrides the manual view and prompt options. The README notes that 64 by 64 output is very small and looks quite bad.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dangeng-visual-anagrams)Was this useful?