AnyBokeh Changes a Photo's Focus and Aperture After You Shot It
A research release from NTU refocuses a photograph on any point and re-renders it at any f-number. The interesting part is what it does with the blur that was already there.
Almost every tool that fakes shallow depth of field starts by trying to undo the blur in your photo. Get back to a clean, everything-sharp version, the thinking goes, and then you can blur it however you like. It sounds sensible. It also throws away the single most useful thing in the frame, which is the blur itself, because the way a lens smears an out-of-focus point of light tells you what that lens was doing at that aperture. Undo it first and you are guessing from scratch. Worse, the errors from the un-blurring step get baked into whatever you render next.
AnyBokeh, released on September 27 by Xinyu Hou, Xiaoming Li, Zongsheng Yue and Chen Change Loy at S-Lab, Nanyang Technological University, and accepted to NeurIPS 2026, skips that step entirely. It reads the existing blur, works out what lens behaviour would produce it, and then re-renders the photo at whatever focus point and f-number you name, relative to what was already there. You can pull focus from the foreground to the background. You can take an f/13 scenic shot and see it at f/2. You can go the other way and sharpen up a frame that was too shallow.
The team calls the thing it estimates an optical fingerprint. That is a good name for it, because it is specific to the picture you handed over, not to a generic lens model.
What you actually get
Two model files, one for each stage, sitting on top of FLUX.1-Fill-dev. Stage one looks at your image and produces two maps: how blurred each part of the picture is and which side of the focal plane it sits on, plus a rough sense of what is near and what is far. Stage two takes your original, both of those maps, and a target, and repaints the picture.
The second stage is the part worth understanding, because it explains why the results do not look like a mask. It compares the blur you have against the blur you asked for, region by region. Where the target calls for more blur than the source has, it adds blur. Where it calls for less, it sharpens. Where they match, it leaves the pixels alone. That is three different operations happening in different parts of the same frame, decided by the difference between two maps rather than by a subject cut-out. This is why it handles the hard cases: a plane of grass receding from the camera, a chain-link fence in front of a face, hair against a busy background.
The project page has an interactive demo where you click a focus point on a sample image and drag an aperture slider from f/2 to f/20. Spend five minutes there before you download anything. It is the cheapest way to find out whether this does what you want.
There is also a smaller claim on that page worth pulling out, because it is the one that determines whether you can use this on your own archive. Most previous work needs you to tell it how blurred the input was, or needs a calibration pass per image to figure that out. AnyBokeh does not. The relationship it fits between blur size and distance is a straight line, and the slope of that line is what it reads off your picture. Scale the slope by the ratio between two f-numbers, shift the sharp plane to the point you clicked, and you have the target. No calibration, no manual guess, one shot per image. For anyone thinking about running this across a folder rather than a hero frame, that is the difference between a script and a full afternoon.
Putting it to work
The setup instructions pin a CUDA 12.4 build of PyTorch, so plan on an NVIDIA card. The environment is otherwise ordinary:
conda create --name anybokeh python=3.10
conda activate anybokeh
pip install torch==2.6.0 torchvision==0.21.0 --index-url https://download.pytorch.org/whl/cu124
pip install diffusers==0.37.0 transformers==5.3.0 peft==0.18.1 accelerate==1.13.0 huggingface_hub==1.6.0
The base model is gated, so go to the FLUX.1-Fill-dev page, accept the licence, and run hf auth login. Everything else downloads on the first run.
Then find your focus point. There is a small tool for this, and it is the detail that tells me a working photographer was in the room when this was designed:
python focus_picker.py --image_path yourphoto.jpg
Open http://127.0.0.1:8000, click the spot you want sharp, and it hands you the two numbers. Now run the edit:
python inference_full.py \
--image_path yourphoto.jpg \
--focus_x 904 --focus_y 613 \
--source_aperture 5.0 --target_aperture 2.8 \
--output_path refocused.jpg
If you do not know what the shot was taken at, drop both aperture flags and use --bokeh_scale 2.0 to double the blur or 0.5 to halve it.
Here is the part most people will skip and should not. The two stages run separately:
python inference_stage1.py --image_path shot.jpg \
--coc_save_path shot_blur.npy --disp_save_path shot_depth.npy
python inference_stage2.py --image_path shot.jpg \
--coc_path shot_blur.npy --disp_path shot_depth.npy \
--focus_x 904 --focus_y 613 --bokeh_scale 2.0 \
--output_path shot_f2.jpg
Stage one is the expensive analysis. Run it once per frame, save the two files, and then re-render that frame at a dozen different focus points and apertures for the cost of stage two alone. If you are working a set of portraits and want three focus options on each for a client to choose from, that is the difference between a long afternoon and a coffee break. Nothing in the documentation pushes you toward this. It should.
Where it breaks
The memory number is the first wall. Running both stages end to end wants about 27 GB, which is not a consumer card. You are renting an hour on a cloud machine, and that is a real cost to factor in before you build a client workflow around it. Running the stages separately helps a lot with repeat renders, but stage one still has to happen once per image on that hardware.
The licence is the second wall and it is higher. The code is under S-Lab License 1.0, and the weights also carry the FLUX.1 [dev] non-commercial terms. Non-commercial means non-commercial. You can learn from this, test it, write about it, and use it on your own pictures for your own pleasure. You cannot put it in a paid retouching pipeline, and you cannot deliver a client image that came out of it. If you are a photographer whose first thought was "this saves me on the next wedding," the answer today is no.
Third: this is early. The repo had 10 stars the morning I looked. The training code is unreleased. The synthetic dataset the team built to train it, with real depth and focus distance and full camera metadata, is listed as coming soon. That matters more than it sounds, because nobody outside the lab can currently retrain this, check it on their own material, or fix it when it fails on a category of image the authors did not test.
Fourth, and this is inherent rather than a bug: the output is a re-render, not a correction layer. Every pixel goes through the model. The authors say plainly that recovering detail from defocus blur is ill-posed, so sharpened regions will differ from what a genuinely in-focus exposure would have shown. Expect small changes in places you did not ask about. If you need the untouched original anywhere in the frame, you will be masking that back in yourself.
Why this is the interesting release of the week
Look at what is being fixed here. Not "generate a better picture." The picture already exists. This is a tool that reaches into a photograph and hands back a decision you thought was locked the moment the shutter closed.
That category is filling up fast. The same weekend, an independent trainer published an add-on that stops an editing model shifting the frame, and someone else published a method for putting the camera at an arbitrary new angle around a still image. Three separate people, none of them at a large lab, working on the same problem from different directions: you have a picture, and the camera choices inside it should not be permanent.
The gap between the demo and the shipped release is where the work is. The interactive demo is wonderful. The download is a non-commercial research artifact that needs a rented graphics card and has no training code. Both things are true, and the honest read is that this is a signpost rather than a tool. The technique will land in something you can use. It will probably not be this repository.
What I would do with it this week: pull one of your own frames where the focus missed, rent an hour of compute, and run it. Not to use the result. To find out whether the thing you have been telling yourself was unfixable actually is. The answer changes what you shoot for.
Medium metadata
Title: AnyBokeh Changes a Photo's Focus and Aperture After You Shot It
Subtitle: A research release from NTU refocuses a photograph on any point and re-renders it at any f-number. The interesting part is what it does with the blur that was already there.
Tags: AI Photography, Photo Editing, Depth Of Field, Computational Photography, Open Source AI
Estimated read time: 7 minutes