Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I am new to Mathematica and trying to figure out whether it is a good tool for algorithmic exploration. So I had the idea of implementing a simple OCR with Mathematica, just using standard algorithms.

I have this picture: Block of text

I'd like to apply the following steps:

  1. Finding the cells of the picture: Could one use a voronoi algorithm to recognize the grid in the picture?

After having the cells I'd like to apply these steps to each:

  1. Use Thinning to find the skeleton of the character.
  2. Use EditDistance to compare the character to a skeletized version of every possible character and then select the character which is closest.

I have seen in the documentation that Mathematica has all these algorithms I am just not sure whether it would actually be feasible to do what I want.

(If it's impossible to do without knowing the name of the font I used: It's "Osaka, Regular-Mono, 144 pt".)

share|improve this question
Yes, it's feasible. Can you show us your initial code? –  belisarius Oct 15 '12 at 21:48
I have no code, alas. E.g. VoronoiDiagram[] expects a list of points, so I would need to somehow convert all my characters to points. Maybe there is a similar function that works directly on images? (Partition?). Once I have an image for each character, I could loop over them (via Table[]) and then apply Thinning[image]. EditDistance[] expects a vector. I would need to create that vector by making changes to a picture and then comparing for equality, not sure if I could do that in Mathematica on a pixel or vector level (Thinning[] only returns an image right? Not the vector data). –  Sven K Oct 15 '12 at 22:00
Look at the help for ImageCorrelate, under Applications i.stack.imgur.com/3tjDp.png –  belisarius Oct 15 '12 at 22:09
Looks very interesting! Looking at the documentation of NormalizedSquaredEuclideanDistance I see that it only takes vectors as arguments. Yet it seems to be possible to use it with the eyes-image as a parameter (I guess?). Could I just replace the eyes-image with a table of images of all possible characters (thinned)? I think this would get me quite close to a solution. –  Sven K Oct 15 '12 at 22:30
@belisarius just hope he's not looking for Schroedinger or Wilson –  acl Oct 15 '12 at 23:24
show 3 more comments

1 Answer

Ok, here is a rather raw intent:

(*define a template font*)
i = Rasterize@Style[" A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ",  
                   FontFamily -> "Courier", FontSize -> 24];

(*separate characters*)
cn = ColorNegate /@ Flatten@ImagePartition[i, ImageDimensions[i]/{26, 1}]

(*define a function for size adjustment*)
let[u_] := Function[{x}, ImageTake[x, Sequence @@ Reverse@Transpose@(u + 
                    ComponentMeasurements[x, "BoundingBox"][[1, 2]])]][#] & /@ cn;

(*set of images for size scaling *)
forSize = let[0];

(*set of images for matching*)
forMatch = let[3 {{-1, -1}, {1, 1}}];

(*Mean template char size*)
sz = N@Mean[ImageDimensions /@ forSize]

(*Now test it*)
i1 = ColorNegate@Rasterize[
   Style[" M Y  L I T T L E  H O U S E  I N  T H E   P R A I R I E   \
                            W A S   A   M E S S   O F   R A T S   A N D  B A T S  ", 
    FontFamily -> "Courier", FontSize -> 25], ImageSize -> 1000]

(* Compute a size factor*)
sizeFactor = -Mean[Mean[Subtract@@@(Range@38/. ComponentMeasurements[i1, "BoundingBox"])]/sz];

(* resize the image to match the template's char size*)
r = Rasterize[i1, ImageSize -> ImageDimensions@i1/sizeFactor];

(*Perform the matching*)
c[t_] := List @@ (ColorData[60][t[[1]]]);
xx = (ImageCorrelate[ r, #, NormalizedSquaredEuclideanDistance] & /@ (Binarize /@ forMatch));
cc = MapIndexed[ImageMultiply[
     With[{k = c[#2]}, Image@Array[k &, Reverse@ImageDimensions[#1]]],
      Dilation[Binarize[ColorNegate@#1, 0.8], DiskMatrix[15]]] &, xx];
rcc = Image[ImageAdd[cc[[#]], r], ImageSize -> {849, 60}] & /@  Range@Length@forMatch;
Fold[ImageAdd[#1, #2] &, rcc[[1]], rcc]

As you can see below the results aren't perfect. There are two obvious improvements to test:

  1. Accept a match after comparing the goodness of all other matchings over a character
  2. Refine the sensibility (0.95 in this test)

Mathematica graphics

Mathematica graphics

share|improve this answer
looks good, but it may not be copy/pasting correctly: "ImageCorrelate::klcst: The distance function NormalizedSquaredEuclideanDistance is not defined for constant kernels. >>" –  cormullion Oct 17 '12 at 8:38
@cormullion Believe it or not, the culprit is the window size of the notebbok. I never saw something like this! Trying to fix it. –  belisarius Oct 17 '12 at 10:45
add comment

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.