テキストの文字を画像化して保存する Python コード例です。
文字を1つずつ描画して、1文字ずつ画像ファイル (.png) に保存していくコードです。
似たような文字を、自動でグループ分けしようと思って書きました。
⇒ 【Python】フォントから『類似文字』の一覧を作成するコード例
文字は、フォントファイルを指定して描画します。
画像の余白も自動で取り除いて、文字の部分だけが残るようにしました。
文字の描画は、Pillow という Python ライブラリで行いました。
※ 収録文字を列挙して画像にするコード例も書きました。
⇒ 【Python】フォントの文字を画像に変換して保存するコード例(余白保持)
Pillow マニュアルの場所
コード例で使用したところの Pillow マニュアルです。
(Pillow) Windows Installation 『Pillow』のインストール方法
(Pillow) PIL.ImageFont.truetype(font=None, size=10, index=0, encoding='', layout_engine=None)
フォント指定
(Pillow) PIL.Image.new(mode, size, color=0)
画像オブジェクト作成
(Pillow) PIL.ImageDraw.Draw(im, mode=None)
描画オブジェクト作成
(Pillow) Image.getbbox()
余白を除いた領域の座標を取得
(Pillow) Image.crop(box=None)
画像を切り抜く
(Pillow) Image.save(fp, format=None, **params)
画像をファイルに保存する
Python マニュアルの場所
コード例で使用したところの Python マニュアルです。
(Python) ord(c)
オード関数。文字の『Unicode コードポイントを表す整数』を取得する
(Python) class pathlib.Path(*pathsegments)
パスオブジェクトを作成
(Python) PurePath.joinpath(*other)
パスを連結する
エフ f
から始まる文字列 f''
は、『エフストリング (f-string)』と呼ばれるものでした。
(Python) フォーマット済み文字列リテラル (f-string)
フォントファイルの場所
M+ FONTS を使わせていただきました。
(mplusfonts.github.io) M+ FONTS
コード例では、『mplus-1m-regular.ttf』を使用しました。
文字がとても読みやすかったです。ありがとうございます。
コード例
テキストの文字を『1文字ずつ』描画して、画像ファイルに保存していく Python コード例です。
from pathlib import Path
from PIL import Image, ImageFont, ImageDraw
def main():
# (設定 1/7) 文字列を決めます。
text = '鑑(かんが)みるぽほ゜。.・,gg990oO'
# (設定 2/7) 画像の保存フォルダを決めます。
data_dir = Path(r'F:\project\images')
# (設定 3/7) フォントファイルを決めます。
# (M+ FONTS を使わせていただきました)
# https://mplus-fonts.osdn.jp/about.html
font_file = r'F:\project\fonts\mplus-1m-regular.ttf'
font_size = 64
font = ImageFont.truetype(font=font_file, size=font_size)
# (設定 4/7) 背景色を『黒 (0, 0, 0)』に決めます。
# .getbbox() メソッドが、黒を余白とみなしてくれるので、
# 黒を使います。
background_color = (0, 0, 0)
# (設定 5/7) フォントの色を決めます。
font_color = (255, 255, 255)
# (設定 6/7) テキストの描画位置を決めます。
position = (0, 0)
# (設定 7/7) 画像サイズを決めます。
# フォントサイズと画像サイズは、だいたいの値です。
# 文字が画像の中に納まるように、何回か試して決めました。
image_size = (96, 96)
# テキストの文字を 1 つずつ取り出して、描画して保存していきます。
for (n, letter) in enumerate(text):
# (描画 1/5) 画像 (Image) オブジェクトを作ります。
im = Image.new(mode='RGB', size=image_size, color=background_color)
# (描画 2/5) 描画 (ImageDraw) オブジェクトを作ります。
draw = ImageDraw.Draw(im)
# (描画 3/5) 文字 (letter) を書きます。
draw.text(xy=position, text=letter, font=font, fill=font_color)
# (描画 4/5) 画像が 0 でない (色が黒でない) 領域の
# 座標 (left, upper, right, lower) を取得します。
bbox = im.getbbox()
# (描画 5/5) 取得した座標で切り出します。
im_crop = im.crop(box=bbox)
# Unicode コードポイントを表す整数を取得します。
# オード関数 ord() は、Python の組み込み関数です。
code_point = ord(letter)
# ファイル名を決めます。
# (例) '{テキストの中での位置}_{Unicode コードポイント}.png'
name = f'{n}_{code_point}.png'
# ファイルパスを決めます。
file = data_dir.joinpath(name)
# 保存します。
im_crop.save(file)
return
if __name__ == '__main__':
main()
実行結果
文字の部分だけを保存した画像ファイルができました。余白もありません。
実際に文字を描画して保存たときの画像ファイル群です。
ところで、1文字ずつだと、フォントが持っていた色々な余白が失われてしまいました。
人間でも、1文字だけでは余白が分かりませんから、仕方がないと思います。
フォントにもよりますが、余白が無いと、『ジー g』と『きゅう 9』がそっくりですね。
※ フォントの余白を保持して画像化するコード例も書きました。
⇒ 【Python】フォントの文字を画像に変換して保存するコード例(余白保持)
『文字の見た目』が役に立つと思った話
例えば、検索エンジンでキーワードを検索するときです。
『見た目が似ている文字』は、あまり区別せずに、一緒に検索したいなって思ったんですよね。
例えば漢字です。字体が異なるものがたくさんありました。
例えば記号です。ドットとか中点(なかてん、中黒、なかぐろ)とかピリオドとか、見た目がほとんど同じ、というものがたくさんありました。
何も無いという『空白文字』でさえ、種類がいくつもありました。
そういった似たような文字たちは、人が文章を読むときみたいに、あまり区別せずに検索したいなって思ったわけです。
文字の正規化にも、限界を感じていたところです。
では、どうしたらいいのか?
『文字を画像化して、似たものを事前にリストアップしておけばいいのではないか?』
そう思ったんですね。
『文字の見た目』が役に立つと思ったわけです。
それで、『文字の見た目』が似ているもの調べるために、文字の画像化が必要になりました。
文字(を表すデータ)にフォントを適用して、画像として扱おうと思い立ちました。
人と同じように、文字を見た目で解釈しようという発想です。
画像化したら、次は機械学習か何かで、似た文字を分類していく感じですね。
そうして、最終的に『似た文字の辞書』を作れたらいいなと、そう思いました。
それがあれば、あいまいな検索ができるんじゃないかと。
例えば、"ド・モルガン"
なら、正規表現で "ド[・.,o゜]モルガン"
みたいな形式に自動変換して、検索できるんじゃないかと。
入力された検索キーワードを1文字ずつチェックして、似た文字の候補があれば、正規表現に含めていこうという作戦です。
結局、プログラムで『人間のように』文字を扱うためには、文字の見た目が必要なんだなって思いましたね。
実際、フォントがなければ、人間はコンピュータの中の文字を読めないわけですし。
『このバイト列は〇〇だな』とか、いちいち対応を覚えていないと読めないです。
あと、本当は1文字ずつじゃなくて、5文字くらいのかたまりで解釈したいところです。
文章を目で追っているときに、その瞬間、その瞬間で認識している文字って、だいたい5文字くらいだったんですよね。
顔文字みたいに、1文字ずつだと、ミスなのか意図したものなのか分からない場面でも、前後の文字から判断できそうです。
1つ文字の表現方法が複数あるケースにも対応できそうです。
濁点付きの文字とか、アクセント記号の表現とか。
そういったものも、文字を画像として扱う過程をへることで、何とかできるんじゃないかと。
さらにいえば、『発音』も役に立つんじゃないかと思っています。
読み仮名ではなくて、音の波形データのことですね。
自分は、文章を読むときに、あたまの中でよく音読しています。
耳の感覚も使って、文字を読んでいました。
人間って、文章を理解するときに、本当に色々な感覚を駆使しているんだなって思いますね。
人と同じような読み方をプログラムに取り入れる試みは、これまで何回も見かけていました。
それで、自分もやってみたいなと、前々からつねづね思っていました。
だって、面白そうじゃないですか。
ただ、あれもこれも同時にプログラムするのは無理なので、まずは文字を画像にしてみるところから書いてみました。