Pythonはいろいろな用途に使えるが、画像や動画処理においても役立つ。しかも、短いプログラムでやりたいことが実現できるので本当心強い。今回は、100枚以上ある画像ファイル全てに、会社名や著作権情報のコピーライトを差し込むプログラムを作ってみよう。
手作業で100枚の画像全部を編集する?!
ネットで買い物をしているときに、商品画像すべてに、販売店の名前が書き込まれているのを見たことがあるだろう。誰かが勝手に画像を使うのを防ぐためだと終われるが、全ての画像を一枚ずつ開いて画像編集ソフトで書き込むのはとても大変だ。プログラミングができるなら、100枚でも200枚でも、あっという間に、コピーライトを書き込むができる。
画像に文字を書き込んでみよう
まずは、画像一枚から試してみよう。今回は、Pythonの画像ライブラリのPillowを使う。AnacondaでPythonを使う場合、最初からインストールされている。もし、インストールされていない場合、コマンドラインから以下のコマンドを実行して、Pillowをインストールしよう。
pip install pillow
また、日本語を使う場合、日本語のフォントファイルが必要だ。今回は、フリーフォントの「みかちゃんフォント」を使ってみよう。こちらのWebサイトからダウンロードしたら、解凍しよう。そして、プログラムから参照しやすいように、ファイル名を「mikachan.otf」という名前に変更して、プログラムと同じフォルダにコピーしておこう。
そして、文字を書き込む画像を準備しよう。ちょうど筆者の友人が文字を書き込むのに良さそうな写真を送ってくれたのを思い出したので、この写真を使ってみよう。
無事、本人の許可も得られたので、この写真を「photo.jpg」という名前で保存しよう。そして、Pythonのプログラムで、キャンバスの中に文字を書き込んでみよう。
画像ファイルに文字を書き込むプログラムは以下のようになる。プログラムを「textout.py」という名前で保存しよう。
# 画像とフォントのパスを指定 --- (*1)
image_path = "photo.jpg"
font_path = "mikachan.otf"
font_size = 50
# 書き込むテキストを指定 --- (*2)
text = "サルも\n木から\n落ちる"
text_pos = (220, 350)
text_color = (0, 0, 0)
# Pillowのライブラリを取り込む --- (*3)
from PIL import ImageFont, ImageDraw, Image
# フォントを読み込む --- (*4)
font = ImageFont.truetype(font_path, font_size)
# 画像を読み込む --- (*5)
image = Image.open(image_path)
# テキストを書き込む --- (*6)
draw = ImageDraw.Draw(image)
draw.text(text_pos, text, fill=text_color, font=font)
# 画像を保存 --- (*7)
image.save("photo-text.png")
print("ok")
そして、コマンドラインから、以下のコマンドを実行すると、「photo-text.png」という名前で文字入りの画像ファイルが出力される。
# Windowsの場合
python textout.py
# macOSの場合
python3 textout.py
実行結果を確認してみよう。うまくキャンバスに文字を書き込むことができた。
プログラムを確認してみよう。(*1)の部分では、画像とフォントのパスを指定する。(*2)では、今回書き込むテキストを変数textに、テキストの書き込み位置を変数text_posに、文字色を変数text_colorに指定する。(*3)の部分では、Pillowのライブラリの取り込みを指定する。(*4)ではフォントを読込み、(*5)では画像を読み込む。(*6)の部分では、テキストを書き込み、(*7)の部分で画像を書き込む。
プログラムの(*2)の部分にあるテキストを書き換えることで、任意のテキストに変更することができる。
大量の画像にコピーライトを書き込もう
画像にテキストを書き込む方法が分かったところで、大量の画像にコピーライトの文字を書き込んでみよう。ここでは、特定のフォルダ以下にあるJPEG画像すべてに、コピーライトを書き込む。
以下のプログラムを「textout_all.py」という名前で保存しよう。
from PIL import ImageFont, ImageDraw, Image
import os, sys, glob
# フォントのパスとサイズを指定 --- (*1)
font_path = "mikachan.otf"
font_size = 40
text_pos = (10, 10)
text_color = (50, 0, 0)
# 出力パスの指定
out_path = "./out"
if not os.path.exists(out_path): os.mkdir(out_path)
# コマンドラインを得る --- (*2)
if len(sys.argv) < 3:
print("textout_all.py フォルダパス テキスト")
quit()
dir_path = sys.argv[1]
label = sys.argv[2]
# フォントを読み込む --- (*3)
font = ImageFont.truetype(font_path, font_size)
# ファイルの一覧を得る --- (*4)
files = glob.glob(dir_path + "/*.jpg")
# 連続で画像にテキストを書き込む --- (*5)
for f in files:
print("textout: " + f)
image = Image.open(f)
draw = ImageDraw.Draw(image)
# 白抜き文字を出力 --- (*6)
for i in range(-3, 4):
for j in range(-3, 4):
x = text_pos[0] + i
y = text_pos[1] + j
draw.text((x, y), label, fill=(255,255,255), font=font)
draw.text(text_pos, label, fill=text_color, font=font)
path = out_path + "/" + os.path.basename(f)
image.save(path)
このプログラムは、任意のパスにあるJPEGファイル(拡張子「.JPG」)を対象に任意のテキストを書き込むものだ。以下の書式で指定する。
python textout_all.py (対象フォルダ) (テキスト)
例えば、以下のように指定すると、testというフォルダにある全ての画像ファイルに、「(c) クジラ飛行机」と書き込んで、「out」というディレクトリに画像ファイルを保存する。
# Windowsの場合
python textout_all.py .¥test "(c) クジラ飛行机"
# macOSの場合
python textout_all.py ./test "(c) クジラ飛行机"
プログラムを実行すると、以下のように、全ての画像にコピーライトが入る。
プログラムを確認してみよう。(*1)の部分では、フォントのパスとサイズを指定する。(*2)では、コマンドラインに与えられた引数を確認する。(*3)の部分では、フォントを読み込む。(*4)の部分で、任意のパスにある画像を読み込み、(*5)の部分で連続で画像ファイルを処理する。(*6)の部分では、ただテキストを書き込むのではなく、文字が白抜きになるように、文字の周囲を白く描画する。
まとめ
以上、今回は画像にテキストを書き込む方法、そして、大量の画像にテキストを書き込む方法を紹介した。前半のプログラムで見たように、画像にテキストを書き込むのは、それほど、難しいプログラムを書く必要はない。加えて、後半のプログラムでは、白抜き文字を書き込む方法も紹介した。画像に文字を書き込む機会は意外と多いので、今回のプログラムが参考になるだろう。
自由型プログラマー。くじらはんどにて、プログラミングの楽しさを伝える活動をしている。代表作に、日本語プログラミング言語「なでしこ」 、テキスト音楽「サクラ」など。2001年オンラインソフト大賞入賞、2004年度未踏ユース スーパークリエータ認定、2010年 OSS貢献者章受賞。技術書も多く執筆している。