Looking online at card.io, there doesn't seem to be much information available about how they do this, however, they seem to be doing a couple of things that would make the problem much easier. They first detect where the edge of the card is in the image. Since the numbers are placed in a uniform location on the card, they then know exactly where each group of four letters are. Maybe they use a projective transform in case the card is rotated a bit or something. The font used for the letters appears to be equally spaced, so in theory, if you have an accurate boundary of the card (which they do), you know location of each number individually and can segment the problem. This would make the recognition problem much eacher .
So let's say I know the location of the numbers. I think this might be enough to try OCR already, but if I want to improve things further, I would try to estimate the background of the card. The function Inpaint
has a number of algorithms for this:
First I would use my knowledge of where the characters are to make a Mask. I've hand drawn one from your first example, but I think a program would do a much better job. I've adjusted the original image a bit since it was kinda dark, but this doesn't really seem to strongly affect how well the method below works.
Let's just call the second image here "mask". Run the original image thru a "FastMarching" algorithm to get an estimation of the background:
background = Inpaint[img, ColorNegate@mask, Method -> "FastMarching"]
There's an estimation of the background values. I'm sure we could do better, but this will probably work fine. Now that we have the background estimated, we can look at the diffrence between the original image and the background:
diff = ImageAdd[background, ColorNegate@img]