Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Over on genealogy.SE, I proposed a method of manipulating images to make "bleed through" less visible and the handwriting on the correct side of the page more legible.

Here are the original images:

enter image description here

enter image description here

The idea is to make a mirror image of the other page, and then remove things that are dark on the flipped page and lighter on the target page, and similarly keep things that are darker on the target page than the flipped page. Here's the flipped page:

page17cropflip = ImageReflect[page17crop, Left]

enter image description here

Here was the set of commands that worked tolerably well in this case (it looks better at full size):

With[{brightness = -0.3`, contrast = 0, final = 0.903`, 
  highbleed = 0.159`, lowbleed = 0.221`, method = "Cluster"}, 
    ImageAdd[Blur[page18crop, 3], 
     ImageClip[page17cropflip, {lowbleed, lowbleed + highbleed}]], {0,
      final}], {contrast, brightness}], Method -> method]]

enter image description here

But I needed to crop the images by hand (I used ImageDifference to help line it up) so that the bleeding through text lined up with the actual text on the image of the facing page. Is there a way to automate this?

share|improve this question
I'm also interested in improvements to my method. I think it could be better. – Verbeia Jul 29 '14 at 10:35
Interesting question. I've done this specific operation by hand before (for full color images rather than text) and I think subtle distortions in the scans will require compensation in the alignment, especially with details as fine as text. I mean that a simple translation will not suffice, and you will need to "warp" the background image to produce a perfect alignment. Many of the image processing tools in v10 are new to me so I'm not sure where to start. Is there a function that is suitable for localized warping? – Mr.Wizard Jul 30 '14 at 1:38
@Mr.Wizard: ImageTransformation can wrap. If you have per-pixel offsets (as you would have with many optical flow or non-parametric registration algorithms), this question might be useful:… – nikie Jul 30 '14 at 5:33
If this weren't a Mathematica-specific site I would suggest a simple manual technique using two minutes of Photoshop: – Rahul Jul 30 '14 at 8:03
@Mr.Wizard, I made an attempt at doing what you describe by doing correlations on smaller sub-images to get a local translation which varies across the image, then interpolating that data and using ImageForwardTransformation to apply the warp. It didn't work very well though. – Simon Woods Jul 30 '14 at 8:04

Here's a first (very simple!) attempt:

{p1, p2} = 
     "Grayscale"] & /@ {"", 

A simple CorrelationDistance gives a surprisingly good estimate for the shift:

corr = ImageCorrelate[p1, ImageReflect[p2, Left -> Right], 

enter image description here

shift = PixelValuePositions[corr, Min[ImageData[corr]]][[1]] - 
shiftedImgs = {p1, 
   ImageTransformation[ImageReflect[p2, Left -> Right], # - shift &, 
    PlotRange -> Full, DataRange -> Full]};

enter image description here

Now, I remember vaguely that PCA was a very cheap way to do blind source separation:

{u, s, v} = 
 SingularValueDecomposition[# - Mean[#] & /@ 
    Flatten /@ ImageData /@ shiftedImgs, 2];
Image[Rescale[Partition[v[[All, 2]], 1000]]]

enter image description here

It seems that the "positive" pixels are one page, the "negative" pixels are the other one. (But I'm probably doing it wrong. I really have to look up how this works again.)

  Function[{sign, mirror},
    Image[1 - 
      Rescale[Clip[sign*Partition[v[[All, 2]], 1000], {0, \[Infinity]}]], 
     ImageSize -> All], mirror]],
   {1, -1},
   {Left -> Left, Left -> Right}

Here's a before/after comparison: enter image description here

Like I said, not perfect. But I think blind source separation techniques really are the way to go here. Both for separating the signal, as well as for choosing a good "correlation measure" to determine the shift between the images. That's why I posted this answer.

share|improve this answer
Thanks nikie, this is excellent, but the real challenge is stripping the bleedthrough of page 17 on page 18. I'm away from my Mathematica machine at the moment, so is there any chance you could show the unflipped version of the second-last image? – Verbeia Jul 29 '14 at 22:45

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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