EasyOCRで日本人だけが読めないフォント「Electroharmonix」を認識させてみた

## はじめに

- ちょっとOCRを試してみたいなと思っていたところ、[EasyOCR](https://github.com/JaidedAI/EasyOCR)というPythonパッケージを見つけた
  - 環境構築や認識する言語の切り替えがお手軽に出来、非常に使いやすい
- 日本人だけが読めないフォントはどう認識するのか、ふと気になり試してみた
  - ソースコードは[こちら](https://github.com/krkettle57/easyocr-electroharmonix)
  - ※後から調べて分かったが[『日本人「だけ」読めないフォント』が本当に日本人だけ読めないのか、ニューラルネットの力を借りて確認してみた](https://qiita.com/lazykyama/items/eae5851b7baaaf4cabd7)という記事が既にある。本記事はこのEasyOCR版だと思って頂ければ...

## EasyOCR

- その名の通り、簡単にOCRが試せるパッケージ
  - [Github](https://github.com/JaidedAI/EasyOCR)
  - [デモページ](https://www.jaided.ai/easyocr/)

### そもそもOCRとは？

- Optical Character Recognitionの略
- ざっくり**画像から文字を抽出して認識する技術**と理解している

## [Electroharmonix](http://typodermicfonts.com/electroharmonix/)

- 日本人だけが読めないフォントと言われているフォント
- ちなみに、下記の画像は~~モレモコヤロカムヤ巾ロウエメ~~Electroharmonixと書いてある
- 記号とかはあるけど、大文字だけで小文字はなさそう

<img src="https://typodermicfonts.com/wp-content/uploads/1998/03/electroharmonix-e-1-scaled.jpg" alt="electorharmonix" style="zoom:75%;" />

(出典: [Electroharmonix)](http://typodermicfonts.com/electroharmonix/)

## 検証方法

1. 下記のフォント使って「Hello, Wolrd」と書かれた画像を生成する
   - electroharmonix
   - IPAex明朝
   - IPAexゴシック
2. EasyOCRで以下の言語を指定して文字認識を実行する
   - 英語
   - 日本語
   - 日本語＆英語
3. EasyOCRの出力した文字列から考察を行う

## 実装

実装といってもテキスト画像生成がメイン

### 事前準備

- electroharmonixを含むいくつかのフォントを比較用にインストールしておく
  - 今回は比較用に[IPAexフォント](https://moji.or.jp/ipafont/ipaex00401/)もダウンロードした
- 必要パッケージのインストール
  - 画像生成に[pillow](https://github.com/python-pillow/Pillow)を用いるがEasyOCRに含まれていたため、EasyOCRのインストールのみで事足りた
  - パッケージ管理には[Poetry](https://github.com/python-poetry/poetry)を利用している

### Pillowを用いた画像生成

主な処理は以下の通り

1. フォントサイズ: 48, 文字色: 黒, 背景色: 白に設定
2. 指定したフォントでテキストを書いた時の領域(幅、高さ)を算出
3. パディングが全体のテキスト領域の10%になるように画像サイズ、テキスト表示位置を設定

```python
@dataclass
class TextImageGenerator:
    font_filepath: str = "fonts/ipaexg.ttf"
    fontsize: int = 48
    px_ratio: float = 0.1
    py_ratio: float = 0.1

    def generate(
        self,
        text: str,
        color: Color = (0, 0, 0),
        bg_color: Color = (255, 255, 255),
    ) -> Image:
        # fontを取得
        font = self._get_font()
        
        # 生成画像のサイズ、テキストの左上位置を取得
        canvas_size, text_tl = self._get_canvas_size(text, font)
        
        # 下地となるImageを作成
        img = self._get_canvas(bg_color, canvas_size)
        
        # 文字を描画
        draw = ImageDraw.Draw(img)
        draw.text(text_tl, text, fill=color, font=font)

        return img

    def _get_canvas_size(self, text: str, font: ImageFont.FreeTypeFont) -> Tuple[Tuple[int, int], Tuple[int, int]]:
        text_width, text_height = ImageDraw.Draw(Image.new("RGB", (200, 200))).textsize(text, font)
        width = int(text_width * (1 + 2 * self.px_ratio))
        height = int(text_height * (1 + 2 * self.py_ratio))

        text_top_left_x = int(width * self.px_ratio / (1 + 2 * self.px_ratio))
        text_top_left_y = int(height * self.py_ratio / (1 + 2 * self.py_ratio))
        return (width, height), (text_top_left_x, text_top_left_y)

    def _get_canvas(self, bg_color: Color, canvas_size: Tuple[int, int]) -> Image:
        return Image.new("RGB", canvas_size, bg_color)

    def _get_font(self) -> ImageFont.FreeTypeFont:
        return ImageFont.truetype(self.font_filepath, self.fontsize)

```

### EasyOCRを用いた各フォント、言語での文字認識

主な処理は以下の通り

- 生成画像に対してEasyOCRで文字認識を実行する
  - 認識した領域ごとに分割されてしまうため、全ての領域の結果を抽出する
- 上記の処理をフォントごと、言語ごとに行う



## 結果

画像生成結果とOCRの認識結果は下記の通り

### 画像生成結果

#### electroharmonix

![gen_electroharmonix_HELLO, WORLD!.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2046285/29d18684-bfc8-ddec-c1ef-a5c618116c9c.png)

#### IPAex明朝

![gen_ipaexm_HELLO, WORLD!.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2046285/29ace8bd-228d-3fc7-737a-2c5cd89a7088.png)

#### IPAexゴシック

![gen_ipaexg_HELLO, WORLD!.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2046285/1e44176c-6c34-a47f-44b5-1f20d37ff20b.png)


### OCR認識結果

| フォント        | 言語         | 結果                    |
| --------------- | ------------ | ----------------------- |
| electroharmonix | 英語         | bELLA; WARlDi           |
| electroharmonix | 日本語       | カモレレロ,山口ポレワ』 |
| electroharmonix | 英語＆日本語 | カモレレロ,山口ポレワ』 |
| IPAex明朝       | 英語         | HELLO, WORLDI' |
| IPAex明朝       | 日本語       | チ_\_0, 0♪\_」 |
| IPAex明朝       | 英語＆日本語 | HELLO,VORLD」 |
| IPAexゴシック   | 英語         | HELLO, WORLDI           |
| IPAexゴシック   | 日本語       | んヒ_\_0一0二\_!       |
| IPAexゴシック   | 英語＆日本語 | HELLOWORLD!             |

## 考察

- electroharmonix
  - 英語としても結構外れてる...
  - 日本人らしい認識だなぁ、一点気になるはヤじゃなくてポって読むのね
  - ロ(ろ)と口(くち)を分けてるところも日本人らしくて個人的にビックリした
  - 英語入れても日本語と一緒
- IPAex系
  - 日本語として読めないのはまぁ分かる
  - 英語でも惜しいけど100点ではない「!」と「I」の違いって確かに結構難しい

## まとめ

- 他の記事でもみられるように、そもそも英語圏の人でも読みやすいフォントではなさそう
- ただ、思ったよりも**日本人寄りの認識結果**だった