Pythonで画面に文字を表示させる方法。PillowとOpenCVの使い方を紹介

今回は、Pillow を使った場合と OpenCV を使った場合の2パターン紹介します。
今回の方法は、かなり前に紹介した物体検出AIプログラム(ウェブカメラで物体を撮影し、SSDで物体検出して数量や物体名をリアルタイムに画面表示させるプログラム)にも使用しています。
OpenCV を知っている方は、cv2.putText() という関数を使って画面に英語を表示させる方法は知っていると思います。
しかし、cv2.putText() では画面に日本語を表示させることができません。
日本語を表示させようとすると「???」のように文字化けしてしまいます。
実は、Pillowを使えば日本語を画面に表示させることができるんです。
しかもリアルタイム表示も可能です。
今回のお話は、画面に日本語を表示させたいと思っている方は必見です!
Pillowで日本語を表示させる方法
以下のソースコードを見てください。
import cv2
import numpy as np
from PIL import ImageFont, ImageDraw, Image
from matplotlib import pyplot as plt
# パラメータ
a = 100
b = 120
c = a + b
# 表示させる文字
nn_jp_0 = "{}{:.0f}{}".format('コーヒー :', a, '円')
nn_jp_1 = "{}{:.0f}{}".format('おにぎり :', b, '円')
nn_jp_2 = "{}{:.0f}{}".format('合計金額 :', c, '円')
# 文字を表示させる画面を作成(黒画面(H, W, C))
img_np_jp = np.zeros((400, 500, 3), np.uint8)
# フォントファイルと文字サイズ(例:42)を指定
font = ImageFont.truetype("./fonts/meiryo.ttc", 42)
# ndarray 型のデータを PIL Image に変換
img_pil = Image.fromarray(img_np_jp)
# Drawにテキストを記載 fillは色 BGRA (RGB)
ImageDraw.Draw(img_pil).text((40, 50), nn_jp_0, font = font , fill = (255, 255, 255, 0))
ImageDraw.Draw(img_pil).text((40, 150), nn_jp_1, font = font , fill = (255, 255, 255, 0))
ImageDraw.Draw(img_pil).text((40, 250), nn_jp_2, font = font , fill = (255, 255, 255, 0))
# 最後に img_pil を ndarray 型データに変換して cv2.imshow() で表示させる
img_np_jp = np.array(img_pil)
cv2.imshow('info_jp', img_np_jp)
cv2.moveWindow('info_jp', 400, 100) # 画面表示位置の指定(Windowの名前, x, y)
cv2.waitKey(0)
cv2.destroyAllWindows()
ソースコードを順に説明します。
はじめに必要なライブラリを import してください。
ポイントは、「 from PIL import ImageFont, ImageDraw, Image 」の部分です。
日本語を表示させる場合は、ndarray 型のデータを一旦 PIL Image データに変換してから文字を書き込みます。
その後、PIL Image データを再度 ndarray 型に変換して cv2.imshow() で表示させます。
慣れない内は煩雑に見えますが、順番にコードを書けばいいだけです。
ちなみに、今回は文字を表示させる画面として np.zeros() を用いています。
np.zeros() は要素がゼロの配列を生成する関数で、ゼロで初期化された ndarray 型のデータとなります。
要素がゼロということは、色で言うと(0,0,0)= 黒ということです。
np.zeros() に似た関数に np.empty() があります。
np.empty() は 配列の各要素がゼロになっていることは保証されていませんが、ゼロで初期化しておく必要がない場合には高速に表示できるメリットがあります。
もし処理速度を少しでも早くしたいと思っているなら np.empty() を使うのもアリだと思います。
次に、ImageFont.truetype() 関数で文字のフォントを指定します。
今回は、meiryo.ttc を使用しています。これは「メイリオ」のことです。
この .ttcファイルは windows10 の場合、以下の階層の先にあるFonts というフォルダにあります。
PC > ローカルディスク(C:)> Windows > Fonts
Fonts フォルダ内に色々な .ttc ファイルがあるので、好きなフォントの .ttc ファイルをコピーしてpython の実行ファイル(xxx.py)が置かれたフォルダ内に入れてください。
これで .ttc ファイルが読み込めるようになります。
次に、先ほど作成した画面を Image.fromarray() を使って ndarray 型から PIL Image に変換します。
その後、ImageDraw.Draw() を使って PIL Image に変換した img_pil に text() を書き込みます。
ImageDraw.Draw() のカッコの中の数字(引数)の意味は以下です。
- 第一引数:画面に文字を表示させる位置。 (横方向, 縦方向)の 意味です。
- 第二引数:表示させる文字
- 第三引数:フォント
- 第四引数:色(BGRA)
最後に img_pil を ndarray 型のデータに変換して cv2.imshow() で表示させます。
実行結果(日本語表示)

ちゃんと日本語が表示されています。
今回は文字のフォントとして「メイリオ」を使いましたが、別なフォントでも表示できます。
興味のある方は試してみてください。
Pillowで英語を表示させるとどうなる?
上記のソースコードを使って、表示させる文字の部分を以下のように修正し実行してみます。
nn_jp_0 = "{}{:.0f}{}".format('coffee :', a, '円')
nn_jp_1 = "{}{:.0f}{}".format('rice ball :', b, '円')
nn_jp_2 = "{}{:.0f}{}".format('total :', c, '円')

ちゃんと英語が表示されています。
しかも日本語も同時に表示することができます。「円」の部分は日本語です。
Pillow を使うと日本語も英語も同時に表示させることができるためとても使いやすいです。
次に、OpenCV を使って画面に文字を表示させてみます。
OpenCVで英語を表示させる方法
以下のソースコードを見てください。
import cv2
import numpy as np
from matplotlib import pyplot as plt
# パラメータ
a = 100
b = 120
c = a + b
# 表示させる文字
nn_us_0 = "{}{:.0f}{}".format('coffee :', a, 'yen')
nn_us_1 = "{}{:.0f}{}".format('rice ball :', b, 'yen')
nn_us_2 = "{}{:.0f}{}".format('total :', c, 'yen')
# 文字を表示させる画面を作成(黒画面(H, W, C))
img_np_us = np.zeros((400, 500, 3), np.uint8)
cv2.putText(img_np_us, nn_us_0, (40, 100), cv2.FONT_HERSHEY_PLAIN, 3, (255, 255, 255), 4, cv2.LINE_AA)
cv2.putText(img_np_us, nn_us_1, (40, 200), cv2.FONT_HERSHEY_PLAIN, 3, (255, 255, 255), 4, cv2.LINE_AA)
cv2.putText(img_np_us, nn_us_2, (40, 300), cv2.FONT_HERSHEY_PLAIN, 3, (255, 255, 255), 4, cv2.LINE_AA)
cv2.imshow('info_us', img_np_us)
cv2.moveWindow('info_us', 900, 100) # 画面表示位置の指定(Windowの名前, x, y)
cv2.waitKey(0)
cv2.destroyAllWindows()
ソースコードを順に説明します。
ポイントは、文字を表示させるときに cv2.putText() を使う所です。
cv2.putText() のカッコの中の数字(引数)の意味は以下です。
- 第一引数:ndarray 型のデータを入力します。今回は画面データ(img_np_us)です。
- 第二引数:表示させる文字
- 第三引数:文字を表示させる位置。(横方向, 縦方向)の意味です。
- 第四引数:フォント
- 第五引数:文字の大きさ
- 第六引数:文字の色。色順は(B, G, R)
- 第七引数:文字の太さ
- 第八引数:線の種類
最後に img_np_us を cv2.imshow() で表示させます。
実行結果(英語表示)

ちゃんと英語が表示されています。
OpenCVで日本語を表示させるとどうなる?
上記のソースコードを使って、表示させる文字の部分を以下のように修正し実行してみます。
nn_us_0 = "{}{:.0f}{}".format('コーヒー :', a, '円')
nn_us_1 = "{}{:.0f}{}".format('おにぎり :', b, '円')
nn_us_2 = "{}{:.0f}{}".format('合計金額 :', c, '円')

画面に日本語は表示されず、文字化けして「???」になってしまいました。
やはり OpenCV の cv2.putText() で日本語を表示させることはできませんでした。
まとめ
- Pillow を使うと画面に日本語が表示できる。
- また色々なフォントで文字が表示できる。
- OpenCV の cv2.putText() でも画面に文字は表示できるが英語しか表示できない。
- cv2.putText() で日本語を表示させようとすると文字化けして「???」のようになる。
ディスカッション
コメント一覧
まだ、コメントがありません