Example 4: Multi-region Character Recognition
This example is similar to Example 3, but instead of analyzing all the features at once, the process of analysis divides them into five topographical regions which focus on individual characteristics of each sample. These five regions, illustrated in Figure 2 below, analyze four quadrants and one central area, all of which overlap to some degree.
After analyzing each sample, the algorithm for each region votes for which class it thinks it sees. The problem inherent in this is when more votes are cast for the wrong prediction (i.e.; three regions think they see a "B" when the sample is actually an "F"). To minimize erroneous majority votes, and maximize accurate votes, each total is weighted with an error factor.
"Fonts" look like the illustration in Figure 1 below. They're simple text files, 35 rows of 70 characters (either "1" or "0"). In case you're curious, I used an ASCII art generator to convert pictures of letters ( although I can only imagine the fun of typing them all in by hand ;-) ).
00000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000011111111000000000000000000000000000000 00000000000000000000000000000111111111100000000000000000000000000000 00000000000000000000000000001111111111110000000000000000000000000000 00000000000000000000000000011111111111111000000000000000000000000000 00000000000000000000000000111111101111111000000000000000000000000000 00000000000000000000000000111111100111111100000000000000000000000000 00000000000000000000000001111111000011111110000000000000000000000000 00000000000000000000000011111110000001111111000000000000000000000000 00000000000000000000000111111100000000111111100000000000000000000000 00000000000000000000001111111100000000111111110000000000000000000000 00000000000000000000001111111000000000011111110000000000000000000000 00000000000000000000011111110000000000001111111000000000000000000000 00000000000000000000111111100000000000000111111100000000000000000000 00000000000000000001111111000000000000000111111100000000000000000000 00000000000000000001111111000000000000000011111110000000000000000000 00000000000000000011111110000000000000000001111111000000000000000000 00000000000000000111111110000000000000000001111111100000000000000000 00000000000000001111111100000000000000000000111111110000000000000000 00000000000000011111111111111111111111111111111111111000000000000000 00000000000000111111111111111111111111111111111111111100000000000000 00000000000001111111111111111111111111111111111111111110000000000000 00000000000001111111100000000000000000000000000111111110000000000000 00000000000011111110000000000000000000000000000011111111000000000000 00000000000011111110000000000000000000000000000011111111000000000000 00000000000111111110000000000000000000000000000001111111100000000000 00000000001111111100000000000000000000000000000000111111110000000000 00000000011111111000000000000000000000000000000000011111111000000000 00000000111111110000000000000000000000000000000000001111111100000000 00000001111111110000000000000000000000000000000000001111111110000000 00000011111111100000000000000000000000000000000000000111111111000000 00000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000
Figure 1. 35 x 70 ASCII rendering of an "A" in the Arial font. This is the content of "A-Arial.txt", one of the many sample files that should be in the same directory with this code's .exe file.
Obviously, VB is not the ideal language to code this algorithm, so it will take a few minutes to run (or longer with the addition of more font sample files).
Modifications can be made to:
Another difference between this example and Example 3, is how the database and feature cue lists are implemented. Here, they're both ArrayLists of ArrayLists (otherwise known as collection objects within collection objects.). This is possible in VB as long as they're treated as objects. Another tricky part to this is making sure that the first elements of all ArrayLists are occupied, even though the algorithm treats them as empty. The AddNewFeature() and PruneOldFeatures() functions ignore the first element, and the Test() function uses the ArrayLists' .clear method but then adds a dummy first element again.
This has to do with how ArrayLists were developed. I don't know this for sure, but I think if an embedded ArrayList is empty, it can't be referenced using the member functions of the ArrayList it's embedded in. When I tried, I'd get error messages. I can imagine the true answer to this is probably more esoteric than I'd understand at this point. So, in the meantime, I'm simply sticking a dummy value of "1" in the each first element.
Four different Windows fonts are analyzed: Arial, Courier New, Tahoma and Times New Roman. fLen = 9, MaxAge = 25, tThreshold = 2.0, PromotionFactor = 1.5, and DemotionFactor = 0.6.
I've found better luck with smaller feature length values than larger ones. When fLen > 10, the algorithm's accuracy gets worse, but with fLen values around 9 or so, the accuracy is far better.
In most cases, each successive exposure to a given letter results in fewer errors.