Basic Cooking #2 - PIL Text


  • Hangul(Korean Letter) Processing
  • Quantizing and anti-aliasing
  • Various font effects using PIL
  • Image Processing using PIL

If the following error occurs in the process of using TrueType fonts.

ImportError: The _imagingft C module is not installed

Then reinstall the Pillow like this.

sudo apt-get install libfreetype6-dev
pip3 uninstall pillow
pip3 install pillow


Hangul(Korean Letter) Processing

Hangul fonts can be used for free Nanum fonts which distributed by Naver or Unicode fonts(Noto Sans CJK KR) downloaded from http://www.google.com/get/noto/#/family/noto-sans-kore .


#!/usr/bin/env python
#-*- coding: utf-8 -*-
#If this code works, it was written by Raspberry.Pi.Maker.
#If not, I don't know who wrote it
#This file should be saved as UTF-8 format.

from PIL import Image, ImageDraw, ImageFont

image = Image.new('RGB', (400, 200),(128, 128, 128))
draw = ImageDraw.Draw(image)
fnt1 = ImageFont.truetype('./font/NanumPen.ttf', 40)
fnt2 = ImageFont.truetype('./font/NanumMyeongjo.ttf', 40)
draw.text((30,30), u'안녕하십니까?', font=fnt1, fill=(0,0,255,128))
draw.text((30,90), u'반갑습니다.', font=fnt2, fill=(0,0,255,128))
image.show()
image.save("./test2.png")

The result of executing the above code is as follows.




Quantizing and anti-aliasing

When representing a True Type font as a bitmap image, use gray tones to smooth the output. This feature, however, produces smooth text output on high-resolution displays such as PCs, but can appear messy on low-resolution LED displays. For low resolution displays, eliminating anti-aliasing can produce much cleaner output.

<Anti-aliased low resolution font image>


To convert an image to Black/White , use PIL API convert


image = image.convert('1')

<B/W converted low resolution font image>

It is recommended to avoid using serif type at low resolution. Now, let's set the threshold value and convert it using lambda expression.



gray = image.convert('L')
bw = gray.point(lambda x: 0 if x < 64 else 255, '1')

<Low resolution font image with threshold conversion>


Various font effects using PIL

I will create various effects while creating the text.

Outline Text

Outline text is the text extracted from the outline of the font as shown in the following figure. gimp and other image editing tools make it easy to create outline text images. Let's see how to make it using PIL.


<Outline text Example>


Let's make an Outline Text Images.



from PIL import Image, ImageDraw, ImageFont, ImageColor

image = Image.new('RGB', (350, 150),(128, 128, 128))
draw = ImageDraw.Draw(image)
fnt = ImageFont.truetype('/usr/local/src/study/image_processing/font/NanumPen.ttf', 60)

fillcolor = (255,255,255)
shadowcolor = (255,0,0)
txt = u'안녕하십니까?'
x = 30
y = 30
thick = 2

#thin border
draw.text((x - thick, y) ,txt, font=fnt, fill=shadowcolor)
draw.text((x + thick, y) ,txt, font=fnt, fill=shadowcolor)
draw.text((x, y - thick) ,txt, font=fnt, fill=shadowcolor)
draw.text((x, y + thick) ,txt, font=fnt, fill=shadowcolor)


#thick border
draw.text((x - thick, y - thick), txt, font=fnt, fill=shadowcolor)
draw.text((x + thick, y - thick), txt, font=fnt, fill=shadowcolor)
draw.text((x - thick, y + thick), txt, font=fnt, fill=shadowcolor)
draw.text((x + thick, y + thick), txt, font=fnt, fill=shadowcolor)

draw.text((x, y), txt, font=fnt, fill=fillcolor)

image.show()
image.save("./tmp/outline.png")

This is an outline text image created by running the code above. You can adjust the thickness of the line, the background color, the line color, and the color of the text.



Paint inside text with background image

Use the AND operation of two images. Fill the text image with (255,255,255) and then AND the background image. Use PIL and OpenCV together.



from PIL import Image, ImageDraw, ImageFont, ImageColor

back = Image.open('./sample/background.png')    #60, 360 pixel size
mask = Image.new('RGBA', back.size,(0,0,0,255))
draw = ImageDraw.Draw(mask)
fnt = ImageFont.truetype('/usr/local/src/study/image_processing/font/NanumGothicExtraBold.ttf', 40)

fillcolor = (0,0,0,0)
txt = u'안녕하십니까?'

draw.text((5, 5), txt, font=fnt, fill=fillcolor)

mask.show()
mask.save("./tmp/mask.png")
back.paste(mask, (0, 0), mask)
back.save("./tmp/masked.png")




The font should be in bold, because the background picture should be represented inside the text. The mask image is then grayscaled.

The following code is processed using PIL only. The result is the same as above. Create a mask image of the same size as the background image (an RGBA type with opacity of 255) and then draw the text on the mask image. In this case, the color of the text must be opacity of 0. The text inside is then transparent. And combine this image with the background image

<background image and processed image>

Image Processing using PIL

In the previous section, we created a new image using PIL and painted the text using a font. However, PIL and other image processing libraries also provide the ability to open, modify, convert, and save existing image files (png, jpg, bmp,…).
Various functions related to images can be found at https://pillow.readthedocs.io/en/3.3.x/reference/Image.html#module-PIL.Image
You can open, create, save, cut, copy, format, and rotate image files using Image. You can also modify images using ImageFilter. ImageDraw lets you draw shapes, draw text, and more.


Adjust the Number of Image Colors Using Quantizing

Quantizing an image reduces the number of colors in the image. Implemented using the functions of PIL. Specifies the number of colors to display in the last colors.



from PIL import Image, ImageDraw, ImageFont
import numpy as np

image = Image.open("./raccoon-dog.png")
result = image.convert('P', palette=Image.ADAPTIVE, colors=5)
result.save("./quantized-raccoon.png")


Custom Colors with Palettes

This time, you can create a palette of colors that you want, and then use the palette colors to quantize them.



image = Image.open("./sample/raccoon-dog.png")

PALETTE = [
    0,   0,   0,  # black,  00
    0,   255, 0,  # green,  01
    255, 0,   0,  # red,    10
    255, 255, 0,  # yellow, 11
] + [0, ] * 252 * 3

pimage = Image.new("P", (1, 1), 0)
pimage.putpalette(PALETTE)
imagep = image.quantize(palette=pimage)
imagep.save('./tmp/quantized-raccoon-palette.png')


<quantizing using convert, palette>


You can download the source codes here(https://github.com/raspberry-pi-maker/OpenCV)









댓글

이 블로그의 인기 게시물

Image Processing #7 - OpenCV Text

OpenCV Installation - Rasbian Buster, Jessie, DietPi Buster

Creating TetrisClock using OpenCV #1