After purchasing a box of alphabet pasta for the kids, I wondered if there was way to extract the frequency of appearance of letters in the box by taken a sample and the analyzing the picture.

i = Import["http://i.imgur.com/qpFUSTo.jpg?1"];
a = Import["http://i.imgur.com/rHD21Gm.jpg"];
bwimg = Binarize@i; bwa = Binarize@a;
x = Table[
   ImageCorrelate[bwimg, ImageRotate[bwa, i], 
    NormalizedSquaredEuclideanDistance], {i, 0, 141 Pi/72, Pi/72}];
y = Table[
  Dilation[ColorNegate@Binarize[x[[i]], 0.07], DiskMatrix[50]], {i, 
   Length[x]}]; z = 
 Fold[ImageAdd, First@y, Rest@y]; HighlightImage[bwimg, z, 
 HighlightColor -> Lighter@Green];
HighlightImage[i, z, HighlightColor -> Lighter@Green]

The result was less than promising, as a) it is time consuming, and b) several letters were missed by the process. I marked with Red and Orange arrows several letters that were missed.

enter image description here

Tried with the Binarize parameter (currently set at 0.07), but increasing it brought false positives into the mix.

Thought about MorphologicalComponents, which is very fast, and if the Colorize option can differentiate the objects, maybe it could be used to extract each letter, then maybe ImageAlign and group together. But that is beyond my skillset.

enter image description here

Any light on how to differentiate and tally the different letters would be appreciated.

  • $\begingroup$ You can greatly simplify the problem. (1) drastically overcook the pasta. (2) Spread as above. (3) They all look the same... but seriously, neat question & demo for the kids. $\endgroup$
    – ciao
    Commented Feb 24, 2014 at 3:31

1 Answer 1


I won't deal with the speed factor yet, mainly with the pattern recognition. It is usually a lot easier to detect patterns using the edge patterns of an image, so you were in the right track with the morphological components.

Using the Schaar 3x3 operators we filter the image so that we can only see the edges:

myedges[v_] := ((ImageData@ImageConvolve[#, {{-3, -10, -3}, {0, 0, 0}, {3, 10, 3}}])^2 +
     (ImageData@ImageConvolve[#, {{-3, 0, 3}, {-10, 0, 10}, {-3, 0, 3}}])^2)&@(Binarize@v);

bwimg = Image[myedges[i]]
bwa = Image[myedges[a]]

enter image description here enter image description here

Where i and a are as given in the question.

Now instead of using bwa, I used bwa inverted left/right. It seemed to me that the side of some of the A's were a bit noisy, and the reserve seems to work better. You can try a combination of Letter and Reverse Letter to do the matching for other letters. (It also may be more natural since I suppose they are made from the same moulds and left/right symmetry may not be perfect in the moulding process) In this case we just use the reversed case:

bwat = ImageRotate[Image[Transpose@(myedges[a])], -Pi/2]    

enter image description here

Using the same approach you did, now using the edge images, with the reversed A edge image:

x = Table[ImageCorrelate[bwimg, ImageRotate[bwat, i], 
NormalizedSquaredEuclideanDistance], {i, 0., 141 Pi/72., Pi/72.}];

y = Map[Dilation[ColorNegate@Binarize[#, 0.26], DiskMatrix[30]] &, 

z = Fold[ImageAdd, First@y, Rest@y];
HighlightImage[i, z, HighlightColor -> Lighter@Green]

enter image description here

We find all the A's!


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.