Redact faces and license plates: Pillow first, AI edit only to replace

For redaction use Pillow boxes you control; use an AI mask edit on openai/gpt-image-2.5 only to replace a plate or face, from $0.0094 per image on Sume.

5 min readSume
All posts

If you must hide faces or license plates before publishing a photo, use deterministic redaction in your own code: a solid rectangle over a box you chose. It is free, repeatable and cannot reconstruct what is underneath. Use an AI edit only when you want a replacement, such as a blank plate or a generic background, and then use mask_url on openai/gpt-image-2.5, billed at $0.009375 on low and $0.0835 on high for a 1024x1024 edit with one input.

A generative edit does not blur anything. It paints new pixels, and a model can paint a plausible plate or a face that looks like a real one. For privacy, that is a different promise from redaction.

Deterministic redaction in Pillow

Detect the regions with whatever detector you trust, or draw the boxes by hand for a small set. Then fill them with solid colour. Blur can be partly recovered when it is light, and a heavy blur on a small face still leaks the skin tone and hair shape, so a solid fill is the safer default for anything private.

from PIL import Image, ImageDraw

im = Image.open("street.jpg").convert("RGB")
draw = ImageDraw.Draw(im)
for box in [(120, 340, 260, 380), (500, 300, 640, 350)]:
    draw.rectangle(box, fill=(0, 0, 0))
im.save("street_redacted.jpg", quality=95)
print("redacted 2 boxes", im.size)

When an AI edit makes sense

Sometimes a black box is ugly, for example in an advertisement where a car must show without a readable plate. In that case a masked edit that replaces the plate with a blank or a generic pattern can look natural. Send the photo as the only input_references entry, the plate mask as mask_url, and ask for a plain white plate with no characters. The Sume docs describe mask_url as a public HTTPS URL for ChatGPT Image 2.5 edits; test the mask convention on one low edit first.

Then verify. Look for characters, partial digits or a plate-like pattern in the result. A model asked for a blank plate may still draw faint glyphs. If there is any chance of a readable plate, fall back to the solid box.

Costs

The pixel route costs nothing. The AI route is billed per completed edit, whatever the outcome; failed jobs are not billed.

Sume cost of a plate or face replacement, one 1024x1024 edit with one input image (read 2026-10-07)
RoutePer image200 photos
Pillow solid box$0$0
GPT Image 2.5 mask edit, low$0.009375$1.875
GPT Image 2.5 mask edit, medium$0.021$4.20
GPT Image 2.5 mask edit, high$0.0835$16.70

Finding the boxes

A detector is the weak link in any redaction pipeline. It finds most faces and plates and misses some, such as small faces at the edge, faces in profile, and plates at steep angles. Review every image with the boxes drawn, count what a human sees against what the detector found, and treat every miss as a leak. For a small set of photos, drawing the boxes by hand is faster and safer than tuning a detector.

Keep the box coordinates next to the file as data. If a photo needs a second pass, you can re-apply the same boxes with extra margin without running detection again. Use generous margins: a plate box should cover the whole plate and its frame, and a face box should include hair and ears, since those identify people too.

Operational notes

Keep the unredacted originals in private storage and publish only the processed files. Strip metadata such as location data from the published copies in your own pipeline, and do not assume an edit job does it for you. Do not send private photos as references to a public URL you do not control, because Sume requires public HTTPS for reference URLs, and a long-lived link to a private image is itself a leak. Use short-lived signed URLs and delete them after the job completes.

Redaction rules vary by country and platform, so treat this as a technical pattern and check your own obligations.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume