質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.20%

pillowで日本語字幕を表示させようとするとフォント指定でエラーが発生してしまう。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 318

genosuke

score 12

前提・実現したいこと

OpenCVとKerasを利用して、webカメラに写されたイラストの顔を検知し判別するプログラムを作りました。
イラストを判別したときに作品名を画面上に日本語で表示させたいと思い、OpenCVは日本語に対応していないとのことなのでpillowを使って表示させようと思ったのですが、フォントのパスの部分
fon = ImageFont.truetype('C:\Windows\Fonts\meiryo.ttc', 27)
でエラーが発生してしまいます。
試しに画像に日本語文字を入れた際に同様のフォントパスを指定してみるとうまく実行できましたのでフォントパスに問題はないと思います。
どなたか解決方法がわかる方、教えていただきたいです。。

イラストの顔を判別するプログラムコードは以下のホームページとほぼ同じ物を書いています
↓                ↓
https://ai-coordinator.jp/real-time-person-detection

発生している問題・エラーメッセージ

Traceback (most recent call last):
  File "C:\Users\Taisei\Anaconda3\envs\opencv\lib\site-packages\PIL\ImageDraw.py", line 309, in draw_text
    mask, offset = font.getmask2(
AttributeError: 'ImageFont' object has no attribute 'getmask2'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "check3.py", line 86, in <module>
    main()
  File "check3.py", line 60, in main
    draw.text((10, 10), u'これはモナリザです。', fill=(255, 0, 0), fon=fon)
  File "C:\Users\Taisei\Anaconda3\envs\opencv\lib\site-packages\PIL\ImageDraw.py", line 352, in text
    draw_text(ink)
  File "C:\Users\Taisei\Anaconda3\envs\opencv\lib\site-packages\PIL\ImageDraw.py", line 330, in draw_text
    **kwargs
  File "C:\Users\Taisei\Anaconda3\envs\opencv\lib\site-packages\PIL\ImageFont.py", line 140, in getmask
    return self.font.getmask(text, mode)
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-9: ordinal not in range(256)
[ WARN:0] terminating async callback

該当のソースコード

import gakusyu2 as face
import sys, os
from keras.preprocessing.image import load_img, img_to_array
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import cv2
import time

cascade_path = 'C:\\Users\\Taisei\\Anaconda3\\envs\\OpenCV\\Lib\\site-packages\\cv2\\data\\haarcascade_frontalface_default.xml'
cascade = cv2.CascadeClassifier(cascade_path)
cam = cv2.VideoCapture(1)
color = (255, 0, 255)

image_size = 32
categories = ["monariza","Lady with an Ermine","Girl with a Pearl Earring"]

def main():

    while(True):
        ret, frame = cam.read()
        facerect = cascade.detectMultiScale(frame, scaleFactor=1.3, minNeighbors=2, minSize=(10, 10))

        frame_img = Image.fromarray(np.uint8(frame))  # numpy.ndarray to Image
        draw = ImageDraw.Draw(frame_img)

        fon = ImageFont.truetype('C:\Windows\Fonts\meiryo.ttc', 27)

        for rect in facerect:
            cv2.rectangle(frame, tuple(rect[0:2]),tuple(rect[0:2] + rect[2:4]), color, thickness=2)
            x = rect[0]
            y = rect[1]
            width = rect[2]
            height = rect[3]

            cv2.imwrite("frontalface.png", frame)
            img = cv2.imread("frontalface.png")

            dst = img[y:y+height, x:x+width]
            cv2.imwrite("output.png", dst)
            cv2.imread("output.png")
            X = []

            img = load_img("output.png", target_size=(image_size,image_size))
            in_data = img_to_array(img)

            X.append(in_data)
            X = np.array(X)
            X  = X.astype("float")  / 256

            model = face.build_model(X.shape[1:])
            model.load_weights("C:\python code\system2.hdf5")

            pre = model.predict(X)
            print(pre)
            if pre[0][0] > 0.95:
                print(categories[0])
                text = categories[0]
                font = cv2.FONT_HERSHEY_PLAIN
                cv2.putText(frame,text,(rect[0],rect[1]-10),font, 2, color, 2, cv2.LINE_AA)
                draw.text((10, 10), u'これはモナリザです。', fill=(255, 0, 0), fon=fon)
            elif pre[0][1] > 0.95:
                print(categories[1])
                text = categories[1]
                font = cv2.FONT_HERSHEY_PLAIN
                cv2.putText(frame,text,(rect[0],rect[1]-10),font, 2, color, 2, cv2.LINE_AA)
                draw.text((10, 10), u'これは真珠の耳飾りです。', fill=(255, 0, 0), fon=fon)
            elif pre[0][2] > 0.95:
                print(categories[2])
                text = categories[2]
                font = cv2.FONT_HERSHEY_PLAIN
                cv2.putText(frame,text,(rect[0],rect[1]-10),font, 2, color, 2, cv2.LINE_AA)
                draw.text((10, 10), u'これは牛乳を注ぐ女です。', fill=(255, 0, 0), fon=fon)

        cv2.imshow("Show FLAME Image", frame)
        #time.sleep(0.1)

        k = cv2.waitKey(1)

        if k == ord('q'):
            break

    cam.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    main()

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

バージョンを確認したところ
Keras 2.3.1
TensorFlow 2.0.0
OpenCV 4.1.0
Python 3.6.8 
pillow 6.2.1
でした。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • meg_

    2020/01/14 20:15

    ・リンクは「リンクの挿入」で記入してください。
    ・モジュールのバージョンを追記してください。

    キャンセル

  • genosuke

    2020/01/15 18:57

    ご指摘ありがとうございます!
    修正しておきます!

    キャンセル

回答 1

checkベストアンサー

+1

【追記】

  1. ImageFont.truetypeのフォント指定の際にはバックスラッシュのエスケープがなくても実行できました。
    失礼しました。

  2. 下記のようにdraw.textの前にフォントを設定すれば良いかと思います。

draw.font = ImageFont.truetype('C:\windows\Fonts\meiryo9.ttc', 27)
draw.text((30, 100), 'あいうえお', (0, 0, 255))


または下記でも良いかと。

font = ImageFont.truetype('C:\windows\Fonts\meiryo.ttc', 27)
draw.text((30, 100), 'あいうえお', font=font, fill=(0, 0, 255))


※フォントを設定しないで日本語を描画しようとしたら質問と同じエラーが出ました。


下記で正しくフォントが設定されていないのではないでしょうか?
(エスケープシーケンスが必要かと思います)

fon = ImageFont.truetype('C:\Windows\Fonts\meiryo.ttc', 27)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/16 18:52

    そうですね!

    キャンセル

  • 2020/01/16 19:41

    fonではなくfontですね。「fon」では駄目だとのエラーが出れば分かりやすいのですが、何故か出ませんね。。

    キャンセル

  • 2020/01/17 15:29

    ご指摘ありがとうございます!
    draw.font = ImageFont.truetype('C:\windows\Fonts\meiryo.ttc', 27)の方で実行してみたところ
    エラーは発生しなくなりましたが、日本語文字は表示されませんでした。。
    プログラムの組み方に問題があるのですかね。。。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.20%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる