From detection to delivery: how AI face cropping works inside Images

Cloudflare’s Image service now ships with AI face cropping available to all users. The feature, first announced in private beta during Developer Week 2024, automatically crops images around detected faces using the gravity=face URL parameter. It joins the existing gravity=auto option, which centers crops on visually salient regions of an image — useful for images of plants or architecture, but far less reliable when the subject is a person.

The distinction matters because images of people make up a large share of traffic for many platforms. One AI chatbot customer, for instance, serves more than 45 million unique transformations each month through Images. For these use cases, getting the focal point right on a human subject is critical — a poorly cropped profile picture or product thumbnail can obscure the very thing the image is meant to show.

Two use cases, one cropping problem

Face cropping addresses two common production workflows. Social media platforms and AI chatbots routinely convert unedited photos of people into small, fixed-shape avatars. E-commerce sites need the same product photo to work in a thumbnail grid and again at a larger size on a product page — where a crop that emphasizes a model’s shirt in one context may need to shift to their sunglasses in another.

With Images, developers don’t have to generate and store multiple derivatives of the same file. The original image remains the single source of truth; each requested transformation is served on demand.

Understanding the gravity of the situation

Image transformations via URL support parameters such as width and height. Without any additional guidance, cropping is applied symmetrically around the center of the original image. The gravity parameter changes the focal point used for cropping — either manually via explicit coordinates or automatically via the gravity=auto saliency algorithm.

Saliency detection identifies regions of visual interest based on cues like color, luminance, and texture. But it doesn’t understand context: a face is just another collection of pixels to a saliency model, not a subject that matters more than the background around it. The gravity=face option closes this gap by detecting actual human faces in the image before deciding where to crop. The zoom parameter, a floating point between 0 and 1, additionally controls how much of the surrounding area gets included around the detected face (or faces) in the final crop.

Privacy was a design constraint from the start. The underlying model detects faces but does not identify them. No facial recognition is performed, and Cloudflare cannot determine whether two different images show the same person.

Choosing the right model for the job

The implementation uses RetinaFace, a convolutional neural network that performs both image classification — determining that a person is present — and object detection — locating exactly where they are in the frame. A CNN processes images in stages, beginning with abstract features like edges and lines before layering in progressively more complex components that, together, constitute a human face.

The selection process weighed several factors. Accuracy was measured against the WIDERFACE benchmark, a dataset of 32,203 images containing 393,703 labeled faces with wide variation in scale, pose, and occlusion. Speed mattered too: most requests happen at delivery time, not upload, so frames per second directly impacts end-user experience. Smaller model sizes were preferred for efficient execution, but not at the cost of output quality.

The team evaluated two-stage detectors (BlazeFast, R-CNN and its successors) against one-stage detectors (RetinaFace, YOLO) on a 500-image test set covering varying number of faces, face sizes, lighting, sharpness, and angles. Two-stage detectors propose candidate regions and then classify objects within them — accurate, but too slow for real-world traffic. One-stage detectors complete both tasks in a single pass and offered better performance while remaining highly accurate. RetinaFace won with 99.4% precision, and handled even images containing multiple blurry faces well.

Managing image size before inference

Sending very large images to a model for inference is computationally expensive. To keep things efficient, a maximum input size of 1024x1024 pixels is enforced. Images already within those dimensions go to the model as-is. Anything larger gets downscaled to an inference image that preserves the original aspect ratio but fits within the 1024-pixel limit on either side. A 125x2000 image, for example, becomes 64x1024 for analysis.

Bounding boxes with brains

Once the model processes the inference image, it yields bounding boxes that define the regions containing each detected face. The system then constructs an outer bounding box that encompasses every individual box. The top-left point takes its x coordinate from the leftmost box and its y coordinate from the topmost box. Symmetrically, the bottom-right point takes its x from the rightmost box and its y from the bottommost box. If a single box borders both the top and the left edge, its top-left corner serves as the outer box’s top-left point.

The focal point for cropping is the center of this outer bounding box. Testing showed that this approach yields better-balanced results for images with multiple faces than alternatives such as anchoring the crop around the largest detected face.

Determining the crop dimensions uses a simple formula: (1 ÷ z) × d, where d is the outer bounding box’s dimensions and z is the zoom level. With zoom=1, the crop matches the bounding box exactly. As zoom trends toward 0, more of the surrounding area is included.

A min function prevents the crop area from exceeding the image’s own boundaries. If the calculated crop extends past the edge of the image, the image’s actual width or height is used instead.

Rescaling back to the original

When a downscaled inference image was used, the crop dimensions must be scaled back up to the original image’s size. If a 2048x2048 image was halved to create a 1024x1024 inference image, every crop dimension gets multiplied by a factor of 2 before the final result is served. A crop area of 400x1024 on the inference image becomes an 800x2048 deliverable.

The end result is a production-ready image that automatically adjusts its focal point based on real human subjects — without the developer needing to store a separate copy for every context where the image will appear.

From CPU bottlenecks to GPU offload

When Cloudflare first beta-tested AI face cropping for its Images product, the inference workload — classifying and locating faces in submitted photos — ran on TensorFlow Rust so it could sit inside the company's existing Rust-based stack. All inference happened on CPUs inside Cloudflare's network, and early tests showed near-realtime performance.

That changed when the team started seeing consistent alerts that the Images service was approaching its memory ceiling. The alerts did not line up with any recent deployments, but a hunch led to a look at the face-cropping compute-time graph, which showed an uptick matching the memory-usage uptick. Further tracing confirmed the feature was the culprit.

CPU-based implementations share RAM with other processes, so when a service runs out of memory and terminates processes to avoid a system crash, it risks taking down unrelated image-optimization operations with it. As a first mitigation, Cloudflare switched the memory allocator from glibc malloc to jemalloc, cutting runtime memory usage by roughly 20 TiB globally. The team also began culling face-cropping requests to bound CPU utilization.

These steps only bought time. AI face cropping was limited to internal use and a handful of beta customers at that point, and even so the reductions were not enough to handle global traffic. A more scalable design was needed.

Moving inference to GPUs with Workers AI

The logical next step was a GPU-based implementation, since GPU memory access is typically dedicated and tightly managed, avoiding the contention that plagues CPU-based approaches. Cloudflare partnered with its Workers AI team, which had built a framework for internal teams to add payloads to its model catalog for GPU access.

Some Workers AI models get their own standalone containers, but that is not practical for every model — routing traffic to many separate containers gets expensive. When a GPU is accessed through Workers AI, data travels over the network, and that latency overhead scales with model size. To keep things tight, Workers AI wraps smaller models together in a single container and uses a latency-sensitive routing algorithm to pick the best instance for each payload. Models can then be offloaded entirely when no traffic is coming in.

A scheduler is used to optimize how — and when — models in the same container interact with GPUs.

A scheduler optimizes how and when models sharing a container interact with the GPUs.

RetinaFace, the model used for face detection, is small enough to be hot-swapped at runtime alongside similarly sized models: it runs in 1 GB of VRAM on the smallest GPU. When a face-cropping request comes in, the Python code is loaded into the environment and executed.

The move to Workers AI produced the expected drop in memory consumption. Each instance of the Images service now uses about 150 MiB of memory.

BLOG-2866 Image 9

The new architecture also reduces the blast radius of memory leaks. Because Workers AI runs models in containers that can be terminated and restarted independently, a leak in the face-cropping process no longer threatens other image operations running in the Images service.

Face cropping in practice on the blog

As part of the beta, Cloudflare applied AI face cropping to author images on the Cloudflare blog. Authors supply their own pictures, which are displayed as circular profile photos in the blog feed and on individual posts. By default, CSS centers images in their containers, which makes off-center head positions stand out — and when two authors' photos have different amounts of negative space, their faces render at visibly different scales.

AI face cropping makes posts with multiple authors appear more balanced.

AI face cropping brings visual balance to posts with multiple authors.

In one co-authored example, the first author's original image crops tightly around his face, while the second author's includes his torso and a wide background margin. After AI face cropping, the two faces appear similar in size, making the post look cohesive.

What's next for AI in Images

Cloudflare positions this as the start of a broader push to automate rote image-editing work for developers who already use Images to build scalable media pipelines. The roadmap includes background removal and generative upscale. AI face cropping is available now — developers can turn it on by enabling transformations in the Images dashboard.