FF14に出てくるエオルゼア文字翻訳アプリ「言語を超える力」。内部としてはTensorFlowを用い、物体検出の推論結果をOpenCVで加工して表示しています。詳しくは以前の記事を。
ここで用いている「Object Detection API」とサンプルスクリプト「Object Detection Tools」では推論結果をOpenCVのputTextで書き込んでいました。しかしputTextは組み込みのフォントしか使えず、フォントがイマイチで、結果があまりキレイに表示されませんでした。
この文字を外部フォントを使ってキレイにしたいという話です。
参考にした記事
【Python】Pillow ↔ OpenCV 変換
TensorFlowとObject Detection ToolsではOpenCVで推論結果を画像に書き込んでいました。その書き込み途中のOpenCVの画像をPillowの画像に変換し、そこでテキストを書き込みます。上記の「OpenCVで日本語フォントを描写する を関数化する」でも変換を行っているのですが、この記事の変換関数の方が使いやすいと思い、参考にさせていただきました。
Noto Sans Japanese
Google Fontsの一つ。今回はこのフォントを使い表示しました。
fonts.google.com
実装
私が実装したコードを参考にどうぞ
Pillow ↔ OpenCV 変換部分
def pil2cv(image): ''' PIL型 -> OpenCV型 ''' new_image = np.array(image, dtype=np.uint8) if new_image.ndim == 2: # モノクロ pass elif new_image.shape[2] == 3: # カラー new_image = cv2.cvtColor(new_image, cv2.COLOR_RGB2BGR) elif new_image.shape[2] == 4: # 透過 new_image = cv2.cvtColor(new_image, cv2.COLOR_RGBA2BGRA) return new_image def cv2pil(image): ''' OpenCV型 -> PIL型 ''' new_image = image.copy() if new_image.ndim == 2: # モノクロ pass elif new_image.shape[2] == 3: # カラー new_image = cv2.cvtColor(new_image, cv2.COLOR_BGR2RGB) elif new_image.shape[2] == 4: # 透過 new_image = cv2.cvtColor(new_image, cv2.COLOR_BGRA2RGBA) new_image = Image.fromarray(new_image) return new_image
上記の変換関数を使って、OpenCVの画像に文字を書き込む部分
def cv2_putText_2(img, text, org, fontFace, fontScale, color): x, y = org b, g, r = color colorRGB = (r, g, b) imgPIL = cv2pil(img) draw = ImageDraw.Draw(imgPIL) fontPIL = ImageFont.truetype(font = fontFace, size = fontScale) w, h = draw.textsize(text, font = fontPIL) draw.text(xy = (x,y-h), text = text, fill = colorRGB, font = fontPIL) imgCV = pil2cv(imgPIL) return imgCV
推論結果のテキストを書き込む部分
colorBGR = (0,0,0) img = cv2_putText_2(img = img, text = information, org = (box[1] + 5, box[2] - 15), fontFace = font_name, fontScale = int(font_size), color = colorBGR)
これはObject Detection Toolsの下記の部分を書き直して使いました。詳しくはObject Detection Toolsを。簡単に説明すると、
- img : OpenCVの画像
- information : 書き込むテキスト
- box : TensorFlowによって推論された座標。この座標を使いやすい形に変えれば、いろんな用途に使えると思います。
cv2.putText(img, information, (box[1] + 15, box[2] - 15), \ cv2.FONT_HERSHEY_SIMPLEX, 1, color, 1, cv2.LINE_AA)
終わりに
とりあえず表示上はきれいになりました。ただ、「言語を超える力」はTensorFlowの推論なので、学習データをもっと上げないと精度自体は上がらないです。もっと学習データを増やさないとですね。今回はここまで。それでは。