Elias M. Nzirorera
Back to the start

Bachelor’s thesis · TUM · 2026

Synthetic Eye Image Generation using Foundation Models

Can an AI-painted background make cheap synthetic eye images more useful for training? I tested it on a single gaming GPU. It helped measurably, and it showed how much is still missing.

University
Technical University of Munich
Chair
Human-Centered Technologies for Learning
Supervisor
Prof. Dr. Enkelejda Kasneci
Degree
B.Sc. Informatics

The problem

Gaze estimation means working out from an image where a person is looking. Training such a model takes a lot of labelled images, and recording real ones is slow and expensive. Tools like UnityEyes can render a million labelled eye images within 24 hours on ordinary hardware, but they draw only the eye region on a flat grey background. Models trained on that struggle with real photos, which is known as the sim-to-real gap.

The research question

How can repainting synthetic images with foundation models improve gaze estimation model performance by closing the domain gap?

The idea

I kept every pixel of the rendered eye and let a diffusion model paint only the grey background, a technique called outpainting. Because the eye itself never changes, the gaze labels stay correct without any new annotation. I called the resulting dataset FluxEyes.

Rendered eye region on a flat grey backgroundUnityEyes
The same rendered eye with a realistic face painted around itFluxEyes
Rendered eye region on a flat grey backgroundUnityEyes
The same rendered eye with a realistic face painted around itFluxEyes
Rendered eye region on a flat grey backgroundUnityEyes
The same rendered eye with a visible square frame around the repainted areaFluxEyes
Left and middle: repaints that work. Right: not every repaint does, this one left a visible frame.

Making it fit on one GPU

I wanted to stay close to the low hardware needs that make UnityEyes popular, so everything ran on a single RTX 4080 with 16 GB of VRAM. With all its components, Flux.1 needs 33 GB, so parts of it spill into far slower CPU memory. Reducing model parameters from 32 to 8 bit and moving to flex2, a smaller community model, cut generation from 42 seconds to about 7 seconds per image. That is still more than two months for a million images, so I set a budget of 48 hours and 20,000 images.

How I tested it

I compared three datasets, each with 20,000 training and 5,000 test images: UnityEyes, FluxEyes, and real photos from ETH-XGaze, filtered to the same head poses and with different people in training and test. On each one I trained a ResNet50, pretrained on ImageNet, for 25 epochs, and then tested every model on every test set.

What came out

Average gaze error in degrees. Lower is better.
Trained onTested on UnityEyesTested on FluxEyesTested on XGaze (real)
UnityEyes1.657.2419.47
FluxEyes2.461.8817.87
XGaze (real)2221.86.22
  • On real photos, the error fell from 19.47° to 17.87°, about 8%, just by repainting the background.
  • The model trained only on UnityEyes did far worse on repainted images: 7.24° instead of 1.65°. I read that as a sign it had leaned on the grey background.
  • The model trained on real photos scored almost the same on both synthetic sets, 22° and 21.8°. Repainting did not disturb the parts of the image that matter for gaze.

Limits and next steps

An error of about 18° is still far from the 6.22° a model reaches when it is both trained and tested on real photos, and 20,000 images is a small set for this field. The next steps I see are replacing the UnityEyes base, and generating the whole image with a retrained diffusion model that takes the gaze target and head pose as inputs.

Built with

  • Python
  • PyTorch
  • OpenCV
  • Flux.1
  • flex2
  • ResNet50
  • UnityEyes

Building something? Tell me about it.

Happy to talk about work, side projects or a good hiking route.