Dear Math-Funsters, As an aspect of my Soviet retrocomputing recreations, I'm trying to extract the font of the original drum printer used before the beginningt of the infamous IBM-cloning program by the Eastern bloc. The starting point is a fairly low-quality (200dpi) scan of a very low quality printout of the diagonal test: http://besm6.sourceforge.net/static_gallery_mirror/images/21_1.jpg (the printer was ~40 years old and the ribbon likely hasn't been re-inked for many years). The charset is GOST-10859. I was able to segment the image into individual tiles 21x33 px automatically using maxima of average intensities per line and per column, accounting for some downward drift toward the right side and the fact that the glyphs are top-heavy due to dot gain as a result of drum surface velocity orthogonal to hammers' velocity . (~100 C++ lines) Then I've implemented a homebrew super-resolution algorithm by iteratively finding min. mean square error per pixel of the overlapping rectangle (i.e. dividing the sum of squared errors by the number of pixels squared to disfavor matching empty corners with empty corners) of the average collected so far and every tile per codepoint. The non-adaptive mean of all tiles, with some contrast enhancement, is used as the seed for the algorithm. (also ~100 C++ lines). (For better results, tiles are normalized (pnmnorm) and edge-enhanced (pgmenhance or pnmnlfilt) before running the super-resolution, and the result is normalized again. This yielded http://mailcom.com/besm6/acpu/enhanced/ As you can see, the top-heavy dot gain is still quite pronounced (e.g. compare the serifs of I, code 102). Then I tried to experiment with erosion algorithms. Straight erosion (new value of a pixel = max({R-nbrhd(pixel)}) is too strong, eating away weak lines. I've came up with new.val = max(cur. pixel, max({R-nbrhd})+min({R-nbrhd})-mean({R-nbrhd \ cur. pixel})) NB that excluding the current pixel from the mean is important to leave a pixel surrounded by white pixels unchanged. This is a much more gentle erosion than the straight maximum. As an experiment, I've changed the formula to be new.val = max({R-nbrhd})+min({R-nbrhd})-mean({R-nbrhd \ cur. pixel}) to see what happens when it is erosion-dilation indifferent. The result is very amusing: http://ic.pics.livejournal.com/spamsink/7162160/44779/44779_original.gif (iteratively applied to the output of 'pgmramp -e 100 100', R = 2.5, neighborhood size 21 pixels) Is there anything I could have done better? Are there smarter super-resolution algorithms? Erosion algorithms? Am I reinventing the wheel with the "water circles" formula new = max({R-nbrhd})+min({R-nbrhd})-mean({R-nbrhd \ cur}) ? Thanks, Leo