プログラミング初心者が
OpenCVと機械学習で
OCRエンジン自作に挑戦する話
marika.h
2019 年 7 月 29 日
@KANSAI AI PUB
自己紹介
marika (@tama_Ud)
バリスタからwebエンジニアに(2019.7~)
プログラミング歴 8ヶ月くらい
よろしくお願いします!
目次
1.OCRってなに?
2.作ってみた
3.まとめ
1.OCRってなに?
OCR (光学文字認識) とは…
フルスペル:Optical Character Recognition
OCRとは、スキャナなどで入力された画像情報の中から、
文字の形状に基づいて文字を識別し、
コンピュータ上で扱える文字データへと変換する仕組みのことである。
(IT用語辞典バイナリより)
たとえば…(ざっくりとしたOCR処理の例)
1234567
890
写真を撮る
or
スキャンする
文字を認識する
読み取った文字を
PC画面に表示する
OSS 業務用 webアプリ
すでに多くのOCRソフトがありますが…
用途や対応言語もさまざま
180の言語に対応できるものもある
今回はOpenCVを使って
自作してみました
2. 作ってみた
認識可能な言語:英数字+記号のみ。
目標:機械学習の基礎の理解と、
システムの完成を目標とする。
精度は求めない。
(現時点の知識では満足のいく
精度を出せませんでした…。)
1. 画像取り込み
2. グレースケール変換
3. レイアウト解析
4. 正規化
5. 特徴抽出
6. 行ごとに取り出す
7. 一文字ずつ取り出す
8. 文字認識
9. 知識処理 etc...
一般的なOCR処理の流れ
1. 画像取り込み
2. 画像のゆがみ補正
3. 二値化
4. 単語ごとに取り出す
5. 一文字ずつ取り出す
6. 正規化
7. 文字認識
今回作るOCR処理の流れ
↑ちょっと簡略化してます
分類器
全体像はこんな感じで作ります
1.画像取り込み・二値化処理
OpenCVのAdaptive threshold()関数で二値化
問題点:光や影の加減でうまく二値化できない時がある。
環境に左右されないようにチューニングするのは難しい…
2. ゆがみ補正
大きなゆがみを検知して、補正します。
1. def _img_rotate(im):
2. avg_gradient = 0
3. #特徴点のx,y座標を取り出す
4. for i in range(len(list_keypoints_x)):
5. kp_x = np.array(keypoints_x[i])
6. kp_y = np.array(keypoints_y[i])
7. #最小二乗法で直線の傾きを取得する
8. #a=傾き,b=切片
9. #傾きの絶対値の最大値を取得
10. ones = np.array([kp_x, np.ones(len(kp_x))])
11. ones = ones.T
12. a,b = np.linalg.lstsq(ones,kp_y)[0]
13. gradients.append(a)
14. max_gradient =gradients[np.argmax(np.abs(gradients))]
15. #画像回転
16. rows,cols = thresh.shape
17. d = math.degrees(avg_gradient)
18. M = cv2.getRotationMatrix2D((cols/2,rows/2),d,1)
19. thresh = cv2.warpAffine(thresh,M,(cols,rows))
AKAZEで特徴量を検出
→クラスタリング
→最小二乗法で文字列の傾
きを求める
→画像を回転させる
3. 単語ごとに取り出す
関数を自作してみたけど
精度が思うように上がらなかったので、
素直にライブラリに頼ります。
OpenCV contribからEASTを使って
単語ごとに認識させます。完璧ですね。
4. 一文字ずつ取り出して正規化
OpenCVのfindcontours()関数で一文字ずつ切り出します
5. 文字認識
1. #英字の認識モデル
2. from keras.models import Sequential
3. def build_model():
4. model = Sequential()
5. model.add(Conv2D(32, kernel_size=(3, 3),
6. activation='relu',
7. input_shape=(28,28,1)))
8. model.add(MaxPooling2D(pool_size=(2, 2)))
9. model.add(Flatten())
10. model.add(Dense(784, activation='relu'))
11. model.add(Dense(52, activation='softmax'))
a. 分類器はkerasで
CNNを構築します
b. 学習
Windows標準フォントを
±20度傾けたり拡大縮小した二値画像で訓練し、
英字 (大文字/小文字)と、数字の重みデータを作成
(この時点で認識精度は87%とあまり良くない)
6. いざ、文字認識
精度は良くない…が
OCRっぽいシステムは出来た!
3. まとめ
・製作期間3ヶ月くらい(python・機械学習も学びながら)
・ライブラリの力を借りれば初心者でもそれっぽいものは作れる
・ブラックボックス化しないようにライブラリのロジックを学ぶ必要あり
・精度を上げるのが難しい(特に情景文字認識の場合)
・実用化するにはさらにチューニングが必要
・OCRエンジンのおおまかな仕組みがわかって良かった
・もっとこうしたほうがいいよ!的なご意見ご指導お待ちしてます!
引用
画像等:
Wikipedia/ Tesseract
https://ja.wikipedia.org/wiki/Tesseract_(%E3%82%
BD%E3%83%95%E3%83%88%E3%82%A6%E3%8
2%A7%E3%82%A2)
Online OCR
https://www.onlineocr.net/
DocuWorks
https://www.fujixerox.co.jp/product/soft
ware/docuworks
参考
NTTデータ/
OCR 技術解説 文字の読み取り・認識について
https://mediadrive.jp/technology/techocr05.html
A gentle introduction to OCR
https://towardsdatascience.com/a-gentle-
introduction-to-ocr-ee1469a201aa
EAST
https://arxiv.org/abs/1704.03155v2
ご清聴ありがとうございました!

プログラミング初心者がOpenCVと機械学習でOCRエンジン自作に挑戦する話