# How to restore an old photo?

I have an old image with scratches that I would like restored. Here is what I have so far:

old = Import["http://i.imgur.com/8pHDEvh.jpg?1"];
mask = Binarize @ TopHatTransform[old, DiskMatrix[2]];
fixed = Inpaint[old, mask, Method -> {"TextureSynthesis"}];
Sharpen[fixed, 2.75]


This code is far from optimal and there are many things I'd like to improve:

1. In masking the scratches I use a disk matrix, but I'm not sure if is that is correct way to go.
2. I have manually chosen the sharpening threshold - this should be automatic.
3. and I'd like to get rid of more of the salt-pepper noise.
• I didn't know my mother was so fond of her old boss. Oh, well, thanks for the eye opener- – Dr. belisarius Mar 21 '16 at 19:43
• 1) The optimal masking is probably found either by ImageLines or manually. 2) You need to define what the "optimum" sharpness is before you automate it. 3) Try MedianFilter or TotalVariationFilter. – dr.blochwave Mar 21 '16 at 20:17
• Also relevant for deblurring: mathematica.stackexchange.com/questions/95164/… – dr.blochwave Mar 21 '16 at 20:21
• The docs example for Inpaint you need to generate the mask by hand, which I don't know how to do quickly, I guess that is another question in and of itself. – M.R. Mar 21 '16 at 20:28
• @M.R. Mathematica has a built-in mask tool when you select an image... – dr.blochwave Mar 21 '16 at 20:38

It seemed to me "scratches" are prominent here and in restoration photography, because they are different from de-noising. There are usually just a few, as in his photo, so you do a few masks. Cracks are easier approached manually then trying to automate their detection, - they can be quite subtle and confused with other parts of the photo. Then developing code that "sees" them is as custom but more complex and time consuming than a good interface for a mask. De-noising is a different problem and I would ask a different question for it, but I think it was answered before on MSE. While I saw no cracks examples besides this one, there are many de-nosing examples, - just search the site or docs - for example this or this. Piling up many complex questions in one usually gets no answers. The method below works very well for few cracks.

I see that you are on the right track using Inpaint, so you probably seen this video:

Image Processing: Real-World Applications

There is an example there that does exactly what you need. Notebook can be downloaded too. The thing that you are lacking is a good interface to build the mask. So here is the example.

Given this image:

let's import it:

lincoln = Import["http://i.stack.imgur.com/rr105.png"]


and find edges and dimensions:

dims = ImageDimensions[lincoln]
edges = EdgeDetect[lincoln]


{371, 432}

The code for the interface design in top animation (a little more detailed explanation in the video I linked):

Manipulate[
LCPP = ListCurvePathPlot[pts, PlotStyle -> Directive[Thickness[th]]];
Row[{Show[lincoln, LCPP, ImageSize -> dims,
PlotRange -> {{0, dims[[1]]}, {0, dims[[2]]}}],
Show[Inpaint[lincoln,
Dilation[
ImageMultiply[edges,
ColorNegate[
Binarize[
Show[LCPP, ImageSize -> dims,
PlotRange -> {{0, dims[[1]]}, {0, dims[[2]]}},
Axes -> False]]]], 1], Method -> method],
ImageSize -> 370]}], {{pts,
RandomReal[Min[ImageDimensions[lincoln]], {3, 2}]}, {0, 0},
ImageDimensions[lincoln], Locator,
Appearance -> Graphics[{Red, Disk[{0, 0}]}, ImageSize -> 7],
LocatorAutoCreate -> {2, 10}}, {{th, .004, "thickness"},
0, .1}, {{method, "Diffusion"}, {"Diffusion", "TotalVariation",
"FastMarching", "NavierStokes", "TextureSynthesis"}, Setter}]

• I don't really see how this answers the question, as the OP's example photo requires much more careful treatment (creases, white spots, black spots and scratches) than this photo of Lincoln. – dr.blochwave Mar 22 '16 at 11:34
• @blochwave I gave my reasoning in the head of my answer. – Vitaliy Kaurov Mar 22 '16 at 15:45