# How to automatically remove text from images?

I'd like to remove the text in the center of images automatically. To use Inpaint[], you need a mask, but I don't have one. So really the problem is:

How to build a mask for an image that contains a known overlaid piece of text?

Here are some example inputs:

• Why can't you post code instead of images? You've been a member here long enough, no? – dr.blochwave Sep 25 '15 at 21:11
• How do you know it's a watermark and not a photo of words floating in the sky? – Simon Woods Sep 25 '15 at 21:25
• "a known logo" and "I don't have the mask" are at least a partial contradiction – Dr. belisarius Sep 25 '15 at 21:32
• ... are we at all concerned that the primary utility of such a tool would be using images without the owners' consent? – Daniel Griscom Sep 26 '15 at 1:37
• Thanks for this question (and the answers). I want to remove place name information from a US government-made map to use in a report with my own data on top of it. US government maps are public domain. I'm sure there are hundreds of other legitimate uses as well. Don't assume the intent is illegal just because that's the only usage your limited imagination can think of. – user9444 May 19 '16 at 23:40

There is a reason why watermarks are there in the first place - to prevent unauthorised reuse of images. For more information on the issues around removing watermarks from images, this Wikimedia article is just one of many useful resources.

The answer below is intended as an exercise in automatically removing text from an image using the inpainting technique. The first part of this answer assumes an unknown text overlay using binarization. The second part of the answer attempts to deal with a known overlay image but unknown position, using image correlation.

## Part 1 - Unknown overlay text, unknown position

For scenarios where the text is a given colour that differs a lot from the rest of the image, this is a job for ChanVeseBinarize[]. It even works fairly well with translucent text - here's an example with a bit of translucent white text, using a Mathematica test image:

image = Import["http://i.stack.imgur.com/LyJTe.png"]

(* This is where parameters become important *)
binimg = ChanVeseBinarize[image, White, {Automatic, 0.12}, MaxIterations -> 1000];

(* Now we can create the mask *)


And finally the inpainting, making use of the method options to improve the result. It introduces a few artifacts due to an imperfect mask (for example, look at the red edge of the nose), but it's not bad given the text was translucent to start off with. With fully-white text, it's much better.

Inpaint[image, maskimg, Method -> {"TextureSynthesis", "MaxSamples" -> 1200}, MaxIterations -> 500]


## Part 2 - Known overlay text, unknown position

This deals with a known piece of overlay text, and makes use of ImageCorrelate[]. Here I make no change to the size or orientation of the overlay, but if you look in the documentation of ImageCorrelate[] under "Generalizations and Extensions" you'll see an example of finding rotated occurrences of a template.

(* The test image is ExampleData[{"TestImage", "Mandrill"}] *)

overlay = Graphics@Text[Style["I love stackexchange", FontFamily -> "Arial",
FontSize -> 32, Bold, White, Opacity[0.8]]];

(* Or you can just import an image I've already prepared *)
compositeimage = Import["http://i.stack.imgur.com/DJEWm.png"]


Then we use ImageCorrelate[] to find the most likely position for the text in the image, and MaxDetect to extract its position (the white dot).

corrimage = ImageAdjust@ImageCorrelate[compositeimage, Binarize@overlay];
maxpos = Flatten@PixelValuePositions[maxdetect, 1];

(* This combines the overlay into a mask at the correct position *)
blankimage = Image@ConstantArray[0, ImageDimensions@compositeimage];
(* Dilation important to ensure full coverage of the mask *)


Finally we can construct a mask from this information and inpaint. Here the performance is much better than above, because the mask is better.

Inpaint[compositeimage, maskimage,
Method -> {"TextureSynthesis", "MaxSamples" -> 1200},
MaxIterations -> 500]


• Your answer is very earnest.But is off track I think,the original question is the fontfamily and its contents is known,but the oriention,size and position is unknown.Then the questioner want to remove it. – yode Sep 26 '15 at 10:35
• Please consider not helping people steal images. – David Richerby Sep 26 '15 at 11:25
• @DavidRicherby I joined this site just to say this: Shut up. The tape recorder wasn't the death of music industry, the VCR not the death of the movie industry and the ability to remove text from images will not be the end of the copyright-on-images thing. – Alec Teal Sep 26 '15 at 23:09
• @AlecTeal And shoplifting won't be the end of grocery stores. But that doesn't mean we should facilitate shoplifting. – David Richerby Sep 27 '15 at 0:53
• Folks, I log on one sunny Sunday afternoon to find eight flags on these comments. I think you all need to take a breath, and please also realise that Mathematica.SE is a reasonably relaxed stack exchange. We moderators do not usually expect to get flags about comments being "too chatty". I recognise that the question could be interpreted as enabling watermark removal, but there are legitimate uses of the technique as well. – Verbeia Sep 27 '15 at 7:19

Here's an alternative approach that uses the functionality of ImageAlign[] to remove the watermark.

pic = ExampleData[{"TestImage", "Lena"}];
watertext =
Image@Graphics@
Text[Style["Welcome to China", Blue, 30, FontFamily -> "Arial"]]


waterimage =
Show[pic,
Graphics@
Text[Style["Welcome to China", Blue, 30,
FontFamily -> "Arial"], {130, 400}]] // Image


ali = ImageAlign[waterimage, watertext,
TransformationClass -> "Perspective"];
ImageCompose[ali, {waterimage, 0.4}]


mask = ali // ChanVeseBinarize[#, Blue] & // Dilation[#, 3] &;