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:

enter image description here enter image description here

  • 8
    $\begingroup$ Why can't you post code instead of images? You've been a member here long enough, no? $\endgroup$ Commented Sep 25, 2015 at 21:11
  • 11
    $\begingroup$ How do you know it's a watermark and not a photo of words floating in the sky? $\endgroup$ Commented Sep 25, 2015 at 21:25
  • 6
    $\begingroup$ "a known logo" and "I don't have the mask" are at least a partial contradiction $\endgroup$ Commented Sep 25, 2015 at 21:32
  • 11
    $\begingroup$ ... are we at all concerned that the primary utility of such a tool would be using images without the owners' consent? $\endgroup$ Commented Sep 26, 2015 at 1:37
  • 5
    $\begingroup$ 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. $\endgroup$
    – user9444
    Commented May 19, 2016 at 23:40

2 Answers 2



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["https://i.sstatic.net/LyJTe.png"]

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

(* Now we can create the mask *)
maskimg = Dilation[DeleteSmallComponents[binimg, 4], 2.5];

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]

enter image description here

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["https://i.sstatic.net/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];
maxdetect = MaxDetect[ImageAdjust@DistanceTransform@Binarize[corrimage, 0.9]];
maxpos = Flatten@PixelValuePositions[maxdetect, 1];

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

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]

enter image description here

  • $\begingroup$ 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. $\endgroup$
    – yode
    Commented Sep 26, 2015 at 10:35
  • 4
    $\begingroup$ Please consider not helping people steal images. $\endgroup$ Commented Sep 26, 2015 at 11:25
  • 19
    $\begingroup$ @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. $\endgroup$
    – Alec Teal
    Commented Sep 26, 2015 at 23:09
  • 2
    $\begingroup$ @AlecTeal And shoplifting won't be the end of grocery stores. But that doesn't mean we should facilitate shoplifting. $\endgroup$ Commented Sep 27, 2015 at 0:53
  • 13
    $\begingroup$ 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. $\endgroup$
    – Verbeia
    Commented Sep 27, 2015 at 7:19

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

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

enter image description here

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

enter image description here

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

enter image description here

mask = ali // ChanVeseBinarize[#, Blue] & // Dilation[#, 3] &;
Inpaint[waterimage, mask, Method -> "TextureSynthesis"]

enter image description here


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.