26
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Tegaki.aiにかける画像をOpenCVで補正

Last updated at Posted at 2018-03-23

#きっかけ
手書き文字認識API(Tegaki.ai)を使ってみました。ルールベースのOCRではなく、AIで手書き文字をデータ化したOCRのようです。認識率99.22%。

サービスの詳細は、HPを参照して欲しい。わくわくする。

本投稿で必要なことだけ説明すると、Tegaki.aiは手書き画像の認識、読取結果取得をAPIで提供していて、そのAPIコールに必要な画像は自分で用意する必要があります。
画像の傾きの補正や、ノイズ除去をすることにより、読取精度が上がりやすいとのことなので、OpenCVで画像補正してみました。

#まずはTegaki.ai使ってみる
Tegaki.aiは有料サービスですが、無料トライアルで使えるみたいなので、早速申し込み。
無料トライアルが使えるようになったので、
まずは、手書き文字認識用の画像を自分で用意しました。
これから手書き文字認識されると思うと、いつもより丁寧に文字を書いてしまいますねw

Tegaki.aiにリクエストを投げて結果を受け取ると、99%の認識率。
画像補正しなくても読取精度が高い結果となりました。誤読された文字も、人間でも読めないかもなーと感じる文字でしたので、まぁよしとしましょう。

次に、業務で使っている手書き書類を使って、tegaki.aiに投げると98%の認識率。

ただ、FAX受信した紙の場合、88%の認識率と精度が低かった。
ここで、FAX受信すると少し縮小されるため、読取位置がずれてしまうのではないか?と仮定して、

FAXの前と後でスキャンした画像の
罫線をぴったりあわせたいと考えました。

結論からいうと、2つの画像を罫線をぴったり合わせることができ、88%→95%まで精度をあげることができました。その過程を本投稿で説明します。
残りの5%は、やはり人間でも読めないような文字や、罫線をはみ出している文字でした。

#実際につかった画像の一部

他にもJANコードや単価、金額などが手書きしてある。
address.png

#Tegaki.aiで提供されているTegaki-editorでデザイン
tegaki-editorでデザインすると、リクエスト用の画像が容易に準備できる。
緑が「単線」フィールド。1行読取
赤が「チェックボックス」フィールド。○囲みや、レ点を読取
「ボックスキャラクター」フィールドもあるが、2018/3時点では数字とカナのみの対応とのこと。

あらかじめデザインした「テンプレート画像」、「読取画像」それぞれの罫線のがぴったり合わないと、読取精度が落ちると思われます。
無題.png

#OpenCVでやったこと
OpenCVを使って、次のような画像補正をしてみた。
・紙をスキャンするときに傾いてしまう→傾き補正(水平に)
・縮小される→リサイズ
※上下逆、手書き文字のかすれ、ノイズ、などの対策はしていない。

#環境
OpenCV3.1
python3.5

#画像補正

##傾き
こちらを参考にしました。
ほぼコピペです。
1.cv2.Canny() でエッジ検出
2.cv2.HoughLinesP()で直線検出
3.水平方向の直線の平均角度を取る
4.直線が水平になるように画像全体を回転
の処理をしています。

今回使用した画像は紙をスキャンしたものですが、スキャンしたときに書類が斜めだと、黒い背景ができますよね。
参考)スキャン画像の左下。
無題1.png

これを直線としてカウントしてしまうと、
3.水平方向の直線の平均角度を取る
で平均角度が適性ではないことがあったので、
唯一変更したのが、if文にarg != 0を追記したことです。

ファイル名:degree.py

import cv2
import numpy as np
import math
import sys
from scipy import ndimage

def get_degree(img):
    l_img = img.copy()
    gray_image = cv2.cvtColor(l_img, cv2.COLOR_BGR2GRAY)
    edges = cv2.Canny(gray_image,50,150,apertureSize = 3)
    minLineLength = 200
    maxLineGap = 30
    lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength,maxLineGap)

    sum_arg = 0;
    count = 0;
    for line in lines:
        for x1,y1,x2,y2 in line:
            arg = math.degrees(math.atan2((y2-y1), (x2-x1)))
            HORIZONTAL = 0
            DIFF = 20
            #arg != 0を条件に追加し、傾きの平均を0に寄りにくくした。
            if arg != 0 and arg > HORIZONTAL - DIFF and arg < HORIZONTAL + DIFF : 
                sum_arg += arg;
                count += 1
    if count == 0:
        return HORIZONTAL
    else:
        return (sum_arg / count) - HORIZONTAL;


if __name__ == "__main__":
    read_file = sys.argv[1]

    img = cv2.imread(read_file)
    arg = get_degree(img)
    rotate_img = ndimage.rotate(img, arg)
    cv2.imwrite('degree.jpg', rotate_img)

実行してみる

> python degree.py input.jpg

degree.jpgというファイル名で出力されます。

一旦、ここまでで投稿。
次回リサイズ

26
26
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?