A box of family prints goes through a scanner and comes out carrying everything that happened to it since 1962. Hairline scratches from a shoebox. A crack across one corner where it was folded. Dust that was on the glass. A crease from a pocket. None of it was in the photograph and all of it is in the file.
Retouching that by hand is an evening per picture, and the evening is not spent on anything skilled. It is spent finding the marks. Once you have found a scratch, painting it out takes seconds. The work is in noticing four hundred of them, most of which you will only see when you finally zoom in far enough.
Finding them, it turns out, is the part a computer is good at, and it does not need a model to do it.
What makes a scratch different from a hair
Physical damage on a print has one property that ordinary picture content does not. It is thin, and it disagrees with its surroundings in almost every direction at once.
Think about a pixel sitting on a real edge in the photograph, the boundary between a dark hillside and a bright sky. Look along the edge and the pixel is in good company: its neighbours to the left and right are the same. Look across the edge and it is completely different from them. So a pixel on an edge disagrees with its surroundings in one direction, maybe two.
A pixel in the middle of a thin scratch has no such company. Whichever way you look, horizontally, vertically or along either diagonal, you leave the scratch within a pixel or two and land in the picture. It disagrees with its surroundings in nearly every direction, and that is a signature nothing in a normal photograph produces.
So the tool estimates, for every pixel, what its surroundings look like along four separate lines: horizontal, vertical and the two diagonals. Then it applies one rule.
damaged = at least 3 of the 4 directions disagree by more than the threshold
Three of four. Not one, which would flag every edge in the picture. Not four, which would miss anything that happens to run parallel to a real edge. Three of four is the entire detector, and it is why this works with arithmetic rather than a model.
Why a median and not an average
The estimate along each line is a median rather than a mean, and that choice is doing real work. An average of a run of pixels that includes the scratch is dragged towards the scratch, so the scratch partly hides itself: the thing you are trying to detect corrupts the measurement you are comparing it against.
A median ignores an outlier rather than absorbing it. Take a line of pixels through a scratch and the scratch is one or two values in a run of nine. The median lands on the surrounding picture and the scratch stands out from it clearly. The width slider is really the length of that run, which is what decides how thick a fault is allowed to be before it stops being treated as a scratch and starts being treated as content.
Everything up to this point runs in this browser tab and no model has been loaded. The marks appear over the picture in red with a count, and both sliders redraw them immediately.
Old photo repair
A scanned print comes back with scratches, cracks, dust specks and fold lines. They all share one property: they are thin, and they sit brighter or darker than the pixels immediately around them, which is something real picture content rarely does in every direction at once. This tool looks for exactly that, shows you what it found so you can correct it by hand, and then asks an inpainting model to fill the marked pixels back in. Your photograph is read in this browser tab and never uploaded. The only thing fetched is the model itself, about 23 MB, from this website, and only after you press the button for it.
or press Enter to pick one. JPEG, PNG or WebP.
Sample photograph, drawn in this browser with damage added on purpose.
Maximum width is how thick a fault is allowed to be before the tool stops calling it a scratch. Raise it for wide cracks, lower it for dust. Both sliders redraw the marks at once, without touching the model.
Drag on the picture with a mouse or a finger. The search cannot tell a hair, an aerial or a blade of grass from a scratch, so the eraser is not an extra, it is part of the job.
The cast is removed on a grey world assumption: the three channel averages are measured and all three are scaled to their common average, which pulls a sepia print back towards neutral. Both controls act on the finished picture, never on the search, and neither of them needs the model.
| What happened | Value |
|---|
What this deliberately cannot do. It does not colourise: a black and white print comes back black and white, and a sepia print comes back sepia unless you ask for the cast to be taken out. It finds thin faults, not large missing corners, because a missing corner has no surroundings for the model to reason from. It mistakes a hair, an aerial or a blade of grass for a scratch often enough that the eraser matters. What gets computed into a gap is plausible, not true: it is the model's guess at what belonged there, and nobody should present it as evidence. And it does not sharpen, so a photograph that was out of focus in 1962 is still out of focus.
How the search works, and why it is done this way. The picture is reduced to grey, and for every pixel the tool estimates what its surroundings look like, separately along four lines through it: horizontal, vertical and the two diagonals. Each estimate is a median, which ignores a thin intruder instead of averaging it in. A pixel counts as damaged only when at least three of the four medians disagree with it by more than the threshold. That rule is the whole point. A real edge disagrees in one or two directions, because along the edge itself the pixel is in good company, while a thin scratch is out of place in nearly every direction at once. The finding is then widened by one pixel so the soft shoulder of a scratch goes with it. Comparable tools exist and several are good. What is different here is only the mechanism: the search is arithmetic in this tab, and the model that fills the gaps is fetched to your browser instead of your picture being sent to someone else's.
The download is re-encoded by the browser, so the scanner metadata the original file carried is not in it. If you want to read what the original held before you replace it, the EXIF viewer on this site shows it without uploading anything either.
Reading the two sliders
Sensitivity is the threshold: how far a pixel has to differ from its estimated surroundings before a direction counts as disagreeing. Turn it down and the tool finds more, including grain and film noise. Turn it up and it finds only the obvious cracks.
Maximum width is the more interesting one, and it is not a sensitivity in disguise. It sets the length of the run each median is taken over, which decides how thick a fault can be before the tool stops treating it as a scratch. At a width of two, a three pixel crack is wider than the tool is looking for and it is invisible. At three, the same crack is found completely.
That behaviour is worth internalising because it explains the failure people hit first: raising sensitivity to find a wide crack does not work and never will, because the crack is not being missed for being too faint. It is being missed for being too fat. Sensitivity is about contrast and width is about size, and reaching for the wrong one produces a frustrating half hour.
The practical order is to set the width to just wider than the widest fault you actually want gone, then bring the sensitivity down until the marks cover the damage, then take the eraser to whatever the picture legitimately contains.
The eraser is not an extra
The detector cannot distinguish a hair on the scanner glass from a hair on somebody’s head. Both are thin, both disagree with their surroundings in every direction, and one of them is the subject of the photograph.
The same is true of an aerial against the sky, a blade of grass, a telephone wire, a mast, a whisker, the rigging on a boat. Every one of those is structurally a scratch and none of them should be removed. There is no threshold that separates them, because the difference is not in the pixels: it is in whether the thin thing was there when the shutter opened.
That is why the tool has a brush and an eraser rather than only a sensitivity slider, and why the marks are shown before anything is filled. The detector’s job is to find four hundred candidates so you do not have to. Deciding which of them are damage is the part that stays with you, and it takes a minute rather than an evening.
Filling the marks in
Once the marks are agreed, the second half is the inpainting model, the same one behind removing an object from a photograph. It reads the picture with the marked pixels cut out and paints them back from what surrounds them.
Two details from that shared machinery matter here. The mask convention is a keep mask, so zero marks the hole and everything else is left alone, and getting it backwards makes the model regenerate the whole photograph instead of the scratches. And the answer is composited rather than adopted: the model returns a complete picture, but only the marked pixels are taken from it, so every unmarked pixel of your scan is byte for byte what it was.
That second point matters more for a scan than for a snapshot. A scanned print has grain, paper texture and tonal character that are the reason it looks like a print rather than a file, and a repair that quietly reworked all of it would have removed the thing you were preserving while fixing the thing you were not.
The finishing is not the model
Two controls sit in their own section and never touch the model: taking the colour cast out, and contrast.
The cast removal is a grey world assumption, which is one line of reasoning. Measure the average of each colour channel across the picture. In a scene with a mixture of colours those three averages should come out roughly equal, so if they do not, the difference is a cast rather than the scene. Scale all three to their common average and the sepia pulls back towards neutral. It is the same principle behind a one click white balance, applied to a print that has aged rather than to a photograph taken under the wrong light.
They are separated deliberately. A visitor who wants to neutralise a sepia print and adjust its contrast can do that without downloading a model at all, and the before and after pair shows a finished picture from the moment a file is loaded rather than an empty box next to a dead control.
Why the search is capped at 1200 pixels
The detector is not cheap. Four directional medians per pixel, each over a run of several values, on every pixel of the picture, and a median is a sort rather than a sum. At full resolution on a scanned print that is a great deal of arithmetic for a browser to do while somebody is dragging a slider.
So the search runs on a copy capped at 1200 pixels on the long edge, and the tool says so rather than doing it quietly. This is a reasonable trade for the specific thing being looked for: damage that is only visible above 1200 pixels is damage nobody sees at any sensible viewing size, and a scratch that matters is a scratch that survives being scaled down.
The median planes are also cached per width, which is why the sensitivity slider re-thresholds instantly while the width slider takes a moment. That asymmetry is not a bug in the interface, it is the shape of the computation showing through, and it is the right way round: sensitivity is the one you fiddle with.
What it deliberately cannot do
It does not colourise. A black and white print comes back black and white, and a sepia print comes back sepia unless you ask for the cast to be taken out. Colourisation is a different model and a different question, and one that invents rather than restores.
It finds thin faults, not large missing corners. A corner that has been torn off has no surroundings for the model to reason from, and what it produces there is a guess rather than a repair. It also does not sharpen: a photograph that was out of focus in 1962 is still out of focus.
And what gets computed into a gap is plausible, not true. It is the model’s guess at what belonged there, based on what surrounds it. For a family photograph that is usually fine and occasionally not, and nobody should present a repaired scan as evidence of anything.
Where it sits
Comparable tools exist and several are good, including ones that run larger models on hardware you do not have. What is different here is only the mechanism: the search is arithmetic running in this tab, and the model that fills the gaps is fetched to your browser instead of your picture being sent to someone else’s.
For a box of family prints that is not a small distinction. Those photographs are the most private things most people own, they usually contain people who never agreed to anything, and the reason to digitise them at all is to keep them rather than to distribute them. If you are working through a stack, it is also worth knowing that a scan carries its own problems beyond damage: a printed original run through a scanner can pick up an interference pattern that is not damage at all and needs a completely different treatment, and the file the scanner writes carries metadata that is worth reading before you share anything.
The idea worth keeping is the three of four rule. It is a single line, it separates damage from content better than any threshold on brightness ever will, and it works because it asks about the shape of the disagreement rather than its size. Most of the useful detectors in image work are like that: not clever models, but a well chosen question that the thing you are looking for answers differently from everything else.