Robo99 (Repo)
Robo99 (Robo99.ttf) is a readability-optimized font whose glyphs were generated using Machine Learning. This whole page is written in Robo99. The goals were to create a font that is
- as readable as possible
- as "normal" as possible
To achieve this, I created a modified Generative Adversarial Neural Network (GAN), with the following modifications:
Only the center of the generator's distribution is used
Usually, when sampling from a GAN, random samples are taken from the generator's probability distribution to create new samples. However, I don't want to create a Halloween font or a Gothic font but a "normal" font.
My intuition is that when I take the center of the generator's probability distribution (a vector of only 0s), the most "normal" font is the result.
Generator can generate each character individually
The generator knows which character it is supposed to generate (a, b, c, etc.), and the discriminator knows the same information. This makes sure that one can control which character the generator is supposed to output. This is also called a Conditional GAN (CGAN).
Generator aims to make font readable
In addition to the regular loss of the generator, which encourages realistic outputs which satisfy the discriminator, I added a pretrained (frozen) font classifier, which encourages the generator to create outputs which are clearly recognizable. For example, if the generator outputs an "R", noise is added to the output and it is blurred randomly. Then the font classifier has to classify it correctly as an "R". This classification loss is added to the loss of the generator.
Speficially, each pixel has a value between 0 (black) and 1 (white). Random gaussian noise is applied to each pixel, with a standard deviation of 0.125. Then a blur with a random standard deviation between 0 and 15 pixels is applied. After that, random gaussian noise with a standard deviation of 0.125 is applied to each pixel again. Finally, each pixel is clipped to a value between 0 and 1.
This figure shows 64 characters from a dataset, to which noise and blur were added.
Tradeoff between satisfying the discriminator and the classifier
The generator has an extra parameter, which controls how much emphasis should be put on readability. It is a number between 0 and 1, where 0 means that the generator should only focus on creating a realistic character, which satisfies the discriminator. 1 means that the generator should only focus on generating a character that can be easily recognized by the classifier under the presence of loss and blur.
The following animation shows how the output font changes, when the readability parameter of the generator is changed from 0 to 1 slowly.
Generating the font
The font is generated by taking the output of the generator when inputting a vector of all zeros for the probability distribution and setting the readability tradeoff parameter to 1 to make sure that the font is as readable as possible. The resulting characters are 64x64 pixel images. Pixel imperfections are manually removed from the images. These images are then vectorized using potrace. The resulting font is generated by importing the vectorized characters into FontForge and merging it with the Ubuntu Regular font. Character width and kerning are automatically done using FontForge. The bold and italic versions are automatically generated. Also special versions of characters (Ü, ä, é, č etc.) are automatically generated.
How to run the code
After installing the requirements (pip install -r requirements.txt
), you can start a training:
python3 gan.py
You can evaluate the readability of the generated fonts by running
python3 gan.py -m export --gan-weights gan_logs/20230728-142502/
You can also use your own weights, if you train your own model. The command also outputs the figure from above, which shows how the characters change when the tradeoff between satisfying the discriminator and the classifier is changed. The text output in the terminal shows why the font is called Robo99. When the tradeoff between satisfying the discriminator and the classifier is 1, the font achieves its highest readability score, which is 99%.
Acknowledgements
The font dataset was taken from https://github.com/erikbern/deep-fonts.