nano bananagpt image 2.5model comparisonimage editingobject removalbounding boxes

Controlled comparison · 7 experiments · 89 generations

Nano Banana 2 vs GPT Image 2.5

We pushed both models to their limit on one deceptively hard task: deleting the object you actually meant, out of a picture full of things that look just like it. Eighty-nine generations, seven controlled experiments, every number measured.

By Daniel Yañez ·

← Blog
Contents · 15 sections

Every image editor built on a generative model inherits a problem from linguistics. To edit an object you must first refer to it, and a reference only works if it picks out exactly one thing. Photographs are full of things that resist that: five identical spheres, two mugs from the same set, three men in black shirts, twenty-six letters where fifteen must go and eleven must stay.

Our own editor failed it in the most literal way possible. Click a detected object, press delete, and every object of the same kind disappears with it. Not sometimes — reliably, because of what the software was sending. This is the study we ran to find out what to send instead, and it turned into a controlled comparison of the two models most people are choosing between right now: gemini-3.1-flash-image (Nano Banana 2) and gpt-image-2.5-sunburst (GPT Image 2.5), with.

Eighty-nine generations, seven experiments, about $8 of API spend. The headline result is not that one model wins. It is that the two models disagree about something more fundamental — which channel to believe when the words and the coordinates point at different objects.

89
image generations
plus 2 more for the artwork above
2
models compared
gemini-3.1-flash-image
gpt-image-2.5-sunburst
7
controlled experiments
one variable changed at a time
7
test images
3 real photographs · 4 synthetic scenes
8
prompt wordings
87 to 255 words, same request
~$7
of API spend
a single working day
Every figure below is measured, not estimated. Where a cell is a single run, the text says so.

The question, stated precisely

A detection row in our database carries two ways of pointing at the same object: a label the scanner wrote (“young man in black tank top”) and a bounding box in coordinates normalised 0–1000. Call these the linguistic channel and the geometric channel. The question is which one a generative editor actually resolves a reference with, and what happens when they conflict.

Three hypotheses were on the table before we started:

  • H1: the label alone is insufficient whenever two objects satisfy it — a **collision**, not a model failure.
  • H2: the box alone is sufficient, and adding it repairs the **collision**.
  • H3: models weight the two channels differently, so a fix that works on one will not transfer.

H1 was confirmed in ten minutes. H2 is what we expected to confirm, spent most of the day trying to confirm, and it is wrong. H3 is what we ended up with, and it has a practical consequence: the correct instruction is not the same for both models.

Method

What the editor was sending

Before anything else, the baseline. Clicking Remove on a detection produced this instruction, verbatim, with the box left behind in the browser:

REMOVE AND REVEAL: Remove “penguin” from the image. Do NOT leave a hole, blank space, or blur. Reveal what would naturally be underneath or behind it.

Run against a scene holding twenty objects of that kind, it removes twenty of twenty. The model is not confused; it is compliant. Every edit in the product travelled as a bare noun.

A phantom, so the scoring is arithmetic

Photographs make poor instruments for this question, because whether something was “removed” is arguable. Medical imaging solves the same problem with a phantom: a manufactured object whose true properties are known exactly, used to calibrate a machine before it is pointed at a patient. We built the equivalent.

Four synthetic scenes — eight, twelve, twenty and thirty identical figures, placed on a jittered grid so that no natural-language ordinal (“third from the left”) can single one out, with deliberate clusters where three overlap and one is left only forty per cent visible. Every figure gets a silhouette mask with the figures painted over it subtracted, so an occluded figure is judged only on the pixels where it actually shows. Removal is then a number: the collapse of dark pixels inside that mask. Over-removal is countable too, and turns out to matter more than the hits.

Three small panels side by side: thirty identical cartoon figures, the same scene after requesting fifteen by coordinate with nine gone, and the same request made with red X marks with only four gone
The phantom. Thirty identical figures, fifteen requested. It exists so that a disagreement about the result is impossible.

Controls and discipline

  • One variable per run. Where a prompt changed, only one clause changed; the two closing sentences were byte-identical across all eight wordings.
  • Cross-model runs used the same string, verified by hash, and the same base image, verified by hash.
  • Two negative controls: the original image differenced against itself, which must be black at any amplification; and the production label-only instruction, which must fail.
  • Scoring is blind to intent — it reads pixels inside masks, not what we hoped would happen.
  • The large claims are single runs. Where a result contradicted an earlier conclusion, it was repeated; those repeats are marked in the text.
test imagesource filefed to both modelsgemini-3.1-flash-image returnedgpt-image-2.5-sunburst returned
phantom scenessynthetic PNG 1024×10241024×1024 PNG1024×1024 JPEG1024×1024 PNG
product renderJPEG 5056×3392 · 17.2 MP1536×1024 PNG1264×843 JPEG · 1.07 MP1536×1024 PNG · 1.57 MP
alphabet sheetJPEG 2528×1696 · 4.3 MP1536×1024 PNG1264×843 JPEG · 1.07 MP1536×1024 PNG · 1.57 MP
concert crowdJPEG 1200×800 · 0.96 MP1536×1024 PNG1264×843 JPEG · 1.07 MP1536×1024 PNG · 1.57 MP
Every input was normalised to one size per test so both models received identical bytes. What came back was neither the same size nor the same format.

Experiment 1 — a real product photograph

A 3D product render with eighteen detections from our own scanner, and two collisions that got there by accident. Five nearly identical blurred spheres float in the background; only two are detected, and those two were requested. Two mugs carry the identical label; one was requested. Seven targets, addressed by coordinate alone, no names attached.

Three panels side by side of a floating product render: the original with seven items outlined in red, Gemini's output with several still present, and GPT's output with all seven gone
Seven requested by coordinate. The detail that does not survive this thumbnail — which mug went, and the three background spheres nobody asked about — is in the table and the viewer below.

gemini-3.1-flash-image removed four of seven. It left both spheres and it resolved the mug collision the wrong way, deleting the one we wanted kept. It also produced the single strangest artefact of the study:

Three crops of the same region: the original showing a handheld gaming console, Gemini's output showing a pair of wireless earbuds in its place, and GPT's output showing the console untouched
Original, Gemini, GPT. The earbuds were on the remove list; the console was not. The earbuds were relocated into the console's place — a substitution, not a deletion.

gpt-image-2.5-sunburst removed all seven, kept the correct mug and kept the console. It also removed the three background spheres nobody asked about. From two instances it inferred a category and applied the deletion to the class — the original bug arriving from the opposite direction: not a label that matches too much, but an induction we never requested.

gemini-3.1-flash-imagegpt-image-2.5-sunburst
of the 7 requested, removed47
the two blurred spheresleft bothremoved both
two identically labelled mugs, one requestedremoved the wrong onecorrect
objects touched that were never requested23 — the undetected spheres
failure modesubstitution and early stopcategorical over-generalisation
One run each. Coordinates only, no names attached.
Both outputs over the original. Drag the gold seam, or switch to difference, where black means identical. Run the negative control first: set the top layer to “original” — it must be pure black at any amplification.

Experiment 2 — twenty-six letters, fifteen of them gone

A cleaner instrument. A specimen sheet of pop-culture letters: fifteen requested of twenty-six, scattered, never two adjacent, addressed only by coordinate. The prompt contains no letter, no name and not the word “letter”. Because the twenty-six glyphs are mutually distinct, there is no category available to over-generalise — which makes this the control for the sphere result above.

Three panels side by side of a pop-culture alphabet: the original twenty-six letters, Gemini's output with eight of the requested letters still present, and GPT's output with exactly the eleven unrequested letters remaining
The claim at a glance. **gpt-image-2.5-sunburst** removed fifteen of fifteen and left every survivor in its own cell; **gemini-3.1-flash-image** removed seven and slid the bottom row left to close the gaps. The viewer below is the same three images at full resolution, layered, if you want to audit rather than glance.
gemini-3.1-flash-imagegpt-image-2.5-sunburst
of the 15 requested, removed715
of the 11 to keep, disturbed00
survivors left in positionno — the bottom row slid left to close the gapsyes, every cell
With no shared category, neither model over-removed. The failure that remains is arithmetic, not semantic.
Try blink on a surviving letter: it alternates the layers every 450 ms, the fastest way an eye catches a shift in position.

Experiment 3 — the dose-response curve

Both real-photograph experiments suggest the same thing: the count of simultaneous targets is a variable in its own right. On the phantom we can measure it properly. Fifteen rungs, climbing from one simultaneous target to fifteen across the four scene densities.

Ask for more, get proportionally less
Fifteen rungs across four scenes. Each dot is one run.
03691215 03691215 everything it was asked for rung 01 · 8 objects · asked 1 · removed 0 · coordinates, the short promptrung 02 · 8 objects · asked 2 · removed 2 · coordinates, the short promptrung 03 · 8 objects · asked 3 · removed 1 · coordinates, the short promptrung 04 · 8 objects · asked 5 · removed 5 · coordinates, the short promptrung 05 · 12 objects · asked 1 · removed 1 · coordinates, the short promptrung 06 · 12 objects · asked 2 · removed 2 · coordinates, the short promptrung 07 · 12 objects · asked 4 · removed 2 · coordinates, the short promptrung 08 · 12 objects · asked 6 · removed 3 · coordinates, the short promptrung 09 · 20 objects · asked 1 · removed 0 · coordinates, the short promptrung 10 · 20 objects · asked 3 · removed 2 · coordinates, the short promptrung 11 · 20 objects · asked 6 · removed 3 · coordinates, the short promptrung 12 · 20 objects · asked 10 · removed 3 · coordinates, the short promptrung 13 · 30 objects · asked 3 · removed 0 · coordinates, the short promptrung 14 · 30 objects · asked 8 · removed 3 · coordinates, the short promptrung 15 · 30 objects · asked 15 · removed 9 · coordinates, the short promptrung 01 · 8 objects · asked 1 · removed 1 · coordinates, the production wrapperrung 02 · 8 objects · asked 2 · removed 1 · coordinates, the production wrapperrung 03 · 8 objects · asked 3 · removed 2 · coordinates, the production wrapperrung 04 · 8 objects · asked 5 · removed 5 · coordinates, the production wrapperrung 05 · 12 objects · asked 1 · removed 0 · coordinates, the production wrapperrung 06 · 12 objects · asked 2 · removed 2 · coordinates, the production wrapperrung 07 · 12 objects · asked 4 · removed 2 · coordinates, the production wrapperrung 08 · 12 objects · asked 6 · removed 4 · coordinates, the production wrapperrung 09 · 20 objects · asked 1 · removed 0 · coordinates, the production wrapperrung 10 · 20 objects · asked 3 · removed 1 · coordinates, the production wrapperrung 11 · 20 objects · asked 6 · removed 1 · coordinates, the production wrapperrung 12 · 20 objects · asked 10 · removed 3 · coordinates, the production wrapperrung 13 · 30 objects · asked 3 · removed 0 · coordinates, the production wrapperrung 14 · 30 objects · asked 8 · removed 2 · coordinates, the production wrapperrung 15 · 30 objects · asked 15 · removed 5 · coordinates, the production wrapperrung 01 · 8 objects · asked 1 · removed 1 · a red X drawn on each targetrung 02 · 8 objects · asked 2 · removed 2 · a red X drawn on each targetrung 03 · 8 objects · asked 3 · removed 1 · a red X drawn on each targetrung 04 · 8 objects · asked 5 · removed 5 · a red X drawn on each targetrung 05 · 12 objects · asked 1 · removed 1 · a red X drawn on each targetrung 06 · 12 objects · asked 2 · removed 0 · a red X drawn on each targetrung 07 · 12 objects · asked 4 · removed 0 · a red X drawn on each targetrung 08 · 12 objects · asked 6 · removed 4 · a red X drawn on each targetrung 09 · 20 objects · asked 1 · removed 0 · a red X drawn on each targetrung 10 · 20 objects · asked 3 · removed 0 · a red X drawn on each targetrung 11 · 20 objects · asked 6 · removed 1 · a red X drawn on each targetrung 12 · 20 objects · asked 10 · removed 0 · a red X drawn on each targetrung 13 · 30 objects · asked 3 · removed 2 · a red X drawn on each targetrung 14 · 30 objects · asked 8 · removed 1 · a red X drawn on each targetrung 15 · 30 objects · asked 15 · removed 4 · a red X drawn on each target objects requested in one call → objects actually removed →
coordinates, the short promptcoordinates, the production wrappera red X drawn on each target
Every point sits on or below the dashed line. The gap is not noise: it widens monotonically with how many objects were requested in a single call.

Twenty-nine of seventy across the ladder for the production prompt. The shape matters more than the total: in ten of fifteen rungs there was zero collateral damage. The model does not remove the wrong figure — it stops early. Ask for ten, receive three, cleanly composited, in an image that looks finished. A system that silently completes a third of a job is more dangerous than one that fails loudly, because the output carries no signal that it stopped.

Experiment 4 — is it the prompt?

The obvious confound. Our production wrapper is 255 words of inherited scaffolding: a preserve list, a conflict-resolution clause, an inventory of what the model can already see. We took the hardest rung — thirty figures, fifteen targets — and rewrote the instruction eight ways, one variable at a time.

Eight wordings, one rung, one variable at a time
30 objects, 15 requested, gemini-3.1-flash-image, one sample each.
051015 three short lines — 9 of 15 removed, 125 wordsthree short lines9of 15 · 125 wordsa centre point, not a box — 7 of 15 removed, 95 wordsa centre point, not a box7of 15 · 95 wordsnative [ymin, xmin] order — 6 of 15 removed, 125 wordsnative [ymin, xmin] order6of 15 · 125 wordsthe production wrapper — 5 of 15 removed, 255 wordsthe production wrapper5of 15 · 255 wordsthe bare order, nothing else — 5 of 15 removed, 87 wordsthe bare order, nothing else5of 15 · 87 wordsbare order + one line of restraint — 5 of 15 removed, 94 wordsbare order + one line of restraint5of 15 · 94 words+ the target count, stated — 4 of 15 removed, 95 words+ the target count, stated4of 15 · 95 wordsthe list numbered 1 to 15 — 1 of 15 removed, 125 wordsthe list numbered 1 to 151of 15 · 125 words
Length is not the variable: 87 words and 255 words land on the same five. Numbering the list — a change of eight characters — costs eight hits.

Nothing beat nine. Not the shortest version, not the longest, not the one written in the model's own native coordinate order. Two deliberate attacks on the early-stopping behaviour — stating the count in prose, numbering the list — both made it worse, and numbering made it dramatically worse: an image returned all but untouched.

One effect did replicate. A single sentence of restraint — “leave every other object exactly the same” — produced the lowest collateral damage in the study at no cost in hits. The hundred-word preserve list bought the same restraint and some timidity with it. With eight phrasings spanning 87 to 255 words all landing between one and nine, we can retire the prompt-length hypothesis: it is not the lever.

Experiment 5 — marking the image instead

If describing the target is unreliable, mark it. Draw a red X on the object and send the annotated photograph. The objection is immediate: you have painted over the customer's picture, and every pixel under the mark must be invented back.

Three zoomed panels of an overlapping cluster: the target's box outlined in blue on the figure behind, a red X at the box centre landing on the figure in front, and the X shifted onto the target's visible head
A prerequisite problem: the centroid of a bounding box need not lie on the object. Blue outlines the target, the figure behind; the centred X lands on its neighbour.

That one is solvable with the boxes alone — choose the point inside the target's box that no other box covers, which lands dead centre on an unobstructed object and slides onto the visible sliver of a buried one. With that in place we mirrored all fifteen rungs: same scenes, same targets, only the pointing changed. Twenty-two of seventy, against twenty-nine for coordinates.

Marking bought nothing and introduced two failure modes coordinates never showed. In two rungs the model took the cheap reading of the instruction: it erased the red crosses and left every figure standing — an output indistinguishable from success without a pixel comparison. In one rung it dissolved the clusters and re-laid the scene into a tidy grid. We also measured the degradation we had feared and found it absent: a marked photograph did not re-render any worse than a clean one.

Experiment 6 — the same prompt, the other model

Three panels side by side: the input scene of thirty identical figures, then outputs from gemini-3.1-flash-image and gpt-image-2.5-sunburst, the second noticeably emptier
Same scene, same fifteen coordinates, same prompt string. Only the model changes.
modelremovedcollateral≈ cost / imagebehaviour
gemini-3.1-flash-image
Nano Banana 2
9 / 153$0.084stops early, cleanly
gpt-image-2.5-sunburst
GPT Image 2.5, quality high
14 / 152$0.053follows the list
Thirty figures, fifteen requested, identical prompt, one run each.

Experiment 7 — what happens when the two channels disagree

Everything so far pointed at a tidy conclusion: send the box as well as the label and the ambiguity goes away. Testing that properly needs an image where a label genuinely collides, on real people rather than clip art. A concert crowd, scanned by our own detection pipeline, which found four foreground people — three of them wearing black.

A dense concert crowd with four people outlined: three in blue labelled black Nike t-shirt, white t-shirt and black t-shirt, and one in gold labelled black tank top, marked as the target
Our scanner's own output. Three of the four detected people satisfy the phrase “a man in a black shirt”. The gold box is the one we requested, every time.

Four conditions, same target throughout. The scanner's descriptive label alone; that label plus its box; a deliberately ambiguous label (“a man in a black shirt”) alone; and the ambiguous label plus the box of the person we actually meant. The last condition is the whole experiment: language and geometry pointing at different people, and we get to see which one the model believes.

what we sentgemini-3.1-flash-imagegpt-image-2.5-sunburst
the scanner's descriptive labelcorrectcorrect
descriptive label + boxcorrectcorrect
ambiguous label aloneremoved nobodyremoved the wrong person
ambiguous label + the correct boxcorrect — the box wonwrong person again — the words won
repeat of the row abovewrong person again
One request, four ways. The bottom two rows are the result the rest of the study did not predict.
Three panels side by side of the concert crowd: the original, Gemini's output where the man in the black tank top is gone, and GPT's output where a different man in a black Nike t-shirt is gone instead
One instruction, containing one set of coordinates, to two models. One deleted the person the box pointed at. The other deleted the person the sentence described.

gemini-3.1-flash-image resolves the reference geometrically. Handed a phrase that fits three people and a box around one, it deletes the one in the box. gpt-image-2.5-sunburst resolves it linguistically. Handed the same pair, it commits to its own reading of the phrase and deletes a man the box does not touch — twice out of twice, with the coordinates sitting right there in the prompt.

This retro-explains the oddest result we had already collected and set aside. On the product render we asked for a single object — the soccer ball — with its box and no name: the only noun in the instruction was the bare word “object”. gpt-image-2.5-sunburst ignored the coordinate and deleted the shopping bag, the hero of the picture. Assuming a bad sample, we repeated the identical prompt twice more. Three runs, three times the wrong object. Reformatted as a bulleted list rather than a sentence: same. With two boxes in the list it got the second one right and still took the bag. That is five box-only requests on this image and five wrong deletions — on the same image where seven boxes in one list came back perfect. A vague noun gives the linguistic channel nothing to resolve, so it falls back on salience and the box does not get a vote. Add the specific name to that same request and it is correct, twice out of twice.

Four panels side by side of the product render: the original, Gemini's output with the soccer ball gone, GPT's output with the ball still there and the shopping bag missing, and GPT's output with the name added where the ball is correctly gone
The single-object case. Panel three is the same coordinate as panel two, ignored. Panel four is that coordinate with the noun attached, obeyed.
The channel-conflict condition, layered. Switch between the two models on the same ambiguous request and watch which person each one decided you meant.

What the seven experiments say together

  • The label alone is a collision hazard, and the collision is ours, not the model's. Twenty of twenty figures removed is correct behaviour for the sentence we sent.
  • The box alone is not a universal repair. It repairs an under-specified reference in gemini-3.1-flash-image and is overridden by a confident wrong reading in gpt-image-2.5-sunburst.
  • A specific, discriminating label is the strongest single signal for both models — which is an argument for the scanner writing distinguishing descriptions, not generic nouns, and ours already does.
  • Simultaneous targets degrade completion independently of ambiguity, and no wording we tried moved that ceiling.
  • Over-removal appears when objects share a category, not when there are many of them. Twenty-six distinct letters: no over-removal. Five near-identical spheres: all five.

Which makes the operational rule a boring one, and different from the one we set out to write. Send both channels, and make the linguistic one specific enough to stand alone — because on one of the two models it will decide the outcome no matter what the coordinates say.

Fidelity: what survives an edit

Wipe between an original and either output and the untouched objects look identical. They are not: both models regenerate the entire frame. Neither returns your pixels.

Two amplified difference maps of the alphabet. Grey marks the regions that were requested; every other letter glows red along its contours in both maps
Amplified six times. Grey is the requested change. Red is everything else that changed anyway — every surviving letter, in both models.

Amplification misrepresents visibility, so: compared pixel to pixel at identical dimensions with nothing resampled between them, the letters we asked to keep differ by a mean of 4 to 10 out of 255, with peaks near 100 on a small fraction of pixels. To the eye, identical.

The obvious explanation — a colour profile, or export compression — is testable and false. Neither file carries an ICC profile, both are 8-bit sRGB, PNG is lossless, and the global signed offset is about −1 per channel. Apply a perfect global tone correction and the residual does not improve by a single point. The residual is instead distributed exactly as regeneration predicts: flat interiors differ by 4, contours and glow by 23. The glyphs were not recoloured; they were redrawn in place, very slightly differently.

On a flat backdrop this is irrelevant. On fine structure it is worth knowing, because contours are what small type, logos and fabric weave are made of. Measured on two brand logos well outside any requested region, both survived at a mean difference of 4, with gpt-image-2.5-sunburst altering 1.4% of their pixels against gemini-3.1-flash-image's 6%.

There is a confound in those numbers that we caught only while writing this up, and it changes one of our own figures, so: gemini-3.1-flash-image returns JPEG. There is no output-format parameter — whatever you send, the bytes that come back are lossy. gpt-image-2.5-sunburst returns what you ask for, and we asked for PNG. Part of the drift measured on Gemini is therefore its own encoder rather than regeneration. The clean measurement — flat interiors differing by 4, contours by 23, and a perfect tone correction improving nothing — was taken on GPT's PNG against a PNG original, and that one stands. Gemini's drift figures should be read as an upper bound that includes a JPEG pass we could not switch off.

Where byte-fidelity is required, the fix is compositional rather than generative: keep the original everywhere and take the model's output only inside the requested boxes, with a soft edge. Measured, 100% of the image outside those regions returns byte-identical. Two implementation notes, both learned by getting them wrong — the mask must be fully opaque across the box and ramp only outside it, or the deleted object's own edge survives at half opacity as a ghost outline; and a shadow falling outside the box will not be cleaned up, because those pixels are by construction the original.

Price, resolution, and what you actually get

gemini-3.1-flash-imagegpt-image-2.5-sunburst
input tokens5381,762 (1,024 = the image)
output tokens1,3901,372
cost per image~$0.084~$0.053
per additional reference image~$0.0003~$0.0082
size requested1K tier1536×1024
size returned1264×8431536×1024
reference resolution effectsizes by total area, so 3:2 lands smaller than 1:1returns the literal size requested
The same 1536×1024 edit with one reference, from the usage each API reported.

The resolution row is the one that surprises people. Gemini sizes its output by total pixel area rather than by long edge, so a 3:2 image at the 1K tier comes back at 1264×843 — narrower than the 1536-wide input we handed it. The edit is returned as a downscale, which is a quality cost that never appears on an invoice.

gemini-3.1-flash-imagegpt-image-2.5-sunburst
how you ask for sizea tier: 1K / 2K / 4Kliteral pixels, e.g. 1536×1024
what decides the resulttotal pixel area — 3:2 lands smaller than 1:1 at the same tierthe number you asked for
practical ceiling4K tier = 4096×4096 = 16.8 MP8.29 MP hard cap, and above 2560×1440 OpenAI marks it experimental — so ~2K is the working ceiling
other limitslong edge 3840, both edges multiples of 16, ratio at most 3:1
output encodingJPEG, no parameter to change itPNG, JPEG or WebP, your choice
The tier-versus-pixels difference is why one request comes back at two different sizes.

Per image, gpt-image-2.5-sunburst came out about a third cheaper: $0.053 against $0.084. Per pixel actually delivered the gap is wider, because the same request returned 1.57 MP from one model and 1.07 MP from the other — $0.034 per megapixel against $0.078, roughly 2.3× cheaper. That ordering inverts with reference count, since GPT charges about $0.0082 per reference image and Gemini about $0.0003: one reference and GPT wins, six and it loses badly. Worth checking against what an operation costs here before planning around either.

Limitations

  • Sample size. Most cells are a single generation. Findings that contradicted an earlier conclusion were repeated — the channel-conflict result twice, the single-object result three times plus two reformats — and those are flagged in the text. The rest should be read as direction, not as a benchmark.
  • Instrument bias. The phantom is flat vector art on a plain field, which makes inpainting easy and may understate the difficulty of removal in textured photographs.
  • One prompt family. Every instruction descends from the same three-sentence ancestor. A structurally different formulation — a conversation, a mask image, a tool call — was not tested.
  • No repeats across models on the real photographs. The crowd conflict is the exception and the one we would most want replicated at scale.
  • Provider drift. These are dated measurements against hosted models that change without notice. Every number here is from a single day.

What we changed

  • Every detection edit now carries its box. Remove, recolour, change material and free-text edits inherit the same repair; all four were suffering the same ambiguity silently.
  • The box travels with the label, never instead of it — and the scanner's obligation to write discriminating labels is now a correctness requirement, not a nicety.
  • One sentence of restraint replaces the hundred-word preserve list. Lowest collateral damage in the study, at no cost in hits.
  • Splitting many targets across sequential passes remains open. Fifteen at once tops out near nine for gemini-3.1-flash-image, and no wording moved it; chained single-target calls are the obvious next experiment and the expensive one, at a generation per object.

Eighty-nine generations and about $8 to discover that the answer was a column we already had, and that it only works on one of the two models unless the column next to it is written well. We will take it.

What we learned, beyond the fix

Five things survived the day that were not on the list of questions we started with, and they are the part we would actually tell a colleague over coffee.

on the evidence heregemini-3.1-
flash-image
gpt-image-2.5-
sunburst
where it was measured
Follows a bounding box when the label is vaguesingle-object test · 3 identical runs + 2 reformats, all box-only
Follows a bounding box when the label is wrongthe crowd test, 2 runs of 2
Follows a discriminating labelboth correct, with or without the box
Completes a long list of targets7 of 15 against 15 of 15 on the alphabet
Leaves unrequested objects aloneit generalised a category and took all five spheres
Keeps survivors in positionit slid a row left to close the gaps
Returns the size you asked for1264×843 for a 1536×1024 request
Returns lossless pixelsJPEG with no parameter to change it
Cheap with one reference image$0.084 against $0.053
Cheap with six reference images$0.0003 against $0.0082 each
✓ held in every run · ≈ held with a caveat · ✗ failed. Ten rows, and neither column is the winner — which is the finding.
  • A model can fail silently and beautifully. The most dangerous output in the whole study was the one that erased our red marks and left every object standing: perfectly composited, plausible, and completely wrong. Any pipeline that edits images on a user's behalf needs a verification step that is not a human glance.
  • For this task, on this evidence, gpt-image-2.5-sunburst is the one we would ship. It finished long lists where gemini-3.1-flash-image stopped around nine, it left unrequested objects in position, it returned the size we asked for in a lossless format, and it cost about a third less per image. We are not going to dress that up as “it depends”.
  • The condition on that recommendation is not small. gpt-image-2.5-sunburst resolves the reference from the words, so a vague or wrong label is obeyed over a correct coordinate — it deleted the wrong person twice with the right box sitting in the prompt. It is the better model here only because our scanner writes discriminating labels. On top of a scanner that writes “person”, it becomes the worse choice and gemini-3.1-flash-image, which follows the box, becomes the safer one.
  • Our own prompt was the confound we examined last. A hundred words of inherited preserve list had quietly turned a capable model into a timid one, and we spent hours suspecting the model before suspecting ourselves.
  • The database already knew. The scanner had been writing a discriminating label and an exact box into the same row since the day it shipped. The failure was entirely in what we chose to read out of it.

And one open question we are leaving on the table honestly: we never found a way to make a single call reliably complete more than about nine deletions. No wording moved it, no marker moved it, and only one of three models got past it. Either that ceiling is a property of how these models plan a composite edit, or we have not found the right shape of request yet. We would rather say that than round it off.

Scan an image and see what it findsEvery image in Nano Studio Pro is detection-scanned: items, colours, textures, and a box for each one.

Keep reading

Nano Banana 2 vs GPT Image 2.5 | Studio Pro