導入
OCR の前処理の第一歩は、たいてい グレースケール化(色を捨てて明るさだけにする)です。文字を読むのに色は不要で、むしろ計算量を1/3に減らし、後の二値化をやりやすくするからです。
説明
from PIL import Image, ImageDraw, ImageFont
import numpy as np
import matplotlib.pyplot as plt
# カラーの文字画像を用意
img = Image.new("RGB", (280, 100), "white")
draw = ImageDraw.Draw(img)
draw.text((15, 25), "Gray", fill=(0, 120, 220), font=ImageFont.load_default(size=52))
gray = img.convert("L") # "L" = 明るさ(luminance)だけの1チャンネル画像
arr = np.array(gray)
print("カラーの形:", np.array(img).shape) # (100, 280, 3)
print("グレーの形:", arr.shape) # (100, 280) ← チャンネルが消えた
fig, ax = plt.subplots(1, 2, figsize=(8, 3))
ax[0].imshow(np.array(img)); ax[0].set_title("color"); ax[0].axis("off")
ax[1].imshow(arr, cmap="gray"); ax[1].set_title("gray"); ax[1].axis("off")
img.convert("L")… 画像をグレースケールに変換します。"L"は「明るさ」を意味するモードです。- グレー画像の配列は
(高さ, 幅)の2次元。チャンネルが1つになり、1ピクセル=1つの明るさ値(0〜255)になります。 plt.subplots(1, 2)で、カラーとグレーを左右に並べて比べています。
色の情報を捨てても、文字の形(明暗の差)は残ります。OCR にとって大事なのは「背景と文字の明るさの差」なので、これで十分なのです。
やってみよう
fill=(0, 120, 220)(青)を別の色に変えても、グレースケールにすると似た明るさになることを確かめましょう。色より「濃さ」が効いていると分かります。
演習
上のコードのグレー画像 arr について、一番暗いピクセルの値(最小値)を print してください。
ヒント1を見る
NumPy 配列の最小値は arr.min() で取れます。print("最小:", arr.min())。
ヒント2を見る
文字(濃い青)の部分が暗いので、0 に近い値が返るはずです。