PythonでOCR

概要

Googleが開発しているtesseractをpythonから呼び出してOCRをしてみる。

環境

環境構築

pip install pyocr
apt install tesseract-ocr libtesseract-dev tesseract-ocr-jpn

必要に応じてpip3にしたりsudoつけたり。 これによって入ってくるtesseractは古いもので精度が悪いことが予想されるので、きちんとやりたい場合はsourceからビルドして入れること。

とりあえず動かす

import sys

from PIL import Image
import pyocr

tools = pyocr.get_available_tools()
assert(len(tools) != 0)
tool = tools[0]

txt = tool.image_to_string(
    Image.open('hoge.png'),
    lang='jpn',
    builder=pyocr.builders.TextBuilder()
)

print(txt)

結果

入力画像

target.png

出力

「内部表現の発見ー獲得・学習」, すなわち, さまざま
な情報が混在し, 雑音で汚れている実世界の観測情報
から, 本質的な情報やある課題 (群) に必要な情報を抽
出し, 処理しやすいよぅに表現することは, 人二二知能や
バターン認識を始めとする知的情幸受処理における古く か
らの研究課題の一っである. この課題に対して, これま
でにさまざまなアプローチでの研究が行われてきたが,
近年, 喜の数が多い階曹的な二ユーラルネッ トヮーク
〈deep neuraー netw。rk: DNN) によってデータから抽象
責の高い村部表現を獲得させる方法が, 深曹学習 (deep
ーearning) と して脚光を浴ぴてぃる. そこで得られた内
部表現を毛いた手法が, 一般物体認識[斑izhevsky ー2],
連続音声認識[Dahー ー2], 自然言語処理, 化合物の活性
予測, などさまざまな分野のコンぺテイショ ンやべンチ
マークタスクで従来法を大き く引き離す性能をたたきだ
してぃることがその直接的な理Jである.

精度ぉ…

精度向上

どうやらtesseract_layoutを適切に設定すると精度が上がる場合があるらしい。 ついでにちょっとプログラムを書き換え

tesseract_layoutの説明

0 = Orientation and script detection (OSD) only.
1 = Automatic page segmentation with OSD.
2 = Automatic page segmentation, but no OSD, or OCR
3 = Fully automatic page segmentation, but no OSD. (Default)
4 = Assume a single column of text of variable sizes.
5 = Assume a single uniform block of vertically aligned text.
6 = Assume a single uniform block of text.
7 = Treat the image as a single text line.
8 = Treat the image as a single word.
9 = Treat the image as a single word in a circle.
10 = Treat the image as a single character.

プログラム

import sys
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

from PIL import Image
import pyocr
import argparse

def main(args: argparse.Namespace) -> None:
    tools = pyocr.get_available_tools()
    assert(len(tools) != 0)
    tool = tools[0]

    txt = tool.image_to_string(
        Image.open(args.target),
        lang='jpn',
        builder=pyocr.builders.TextBuilder(tesseract_layout=6) # ここが重要
    )

    print(txt)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('target', type=str, help='target image')
    args = parser.parse_args()

    main(args)

ついでにDocker化

Dockerfile

from ubuntu:18.04

MAINTAINER masataka.hisasue <masataka.hisasue@optim.co.jp>

RUN apt update && \
    apt install -y libtesseract-dev tesseract-ocr tesseract-ocr-jpn python3 python3-pip && \
    pip3 install pyocr

COPY main.py /
COPY hoge.png /

CMD ["python3", "main.py", "hoge.png"]

ビルド

docker build -t ocr .

実行

docker run -it --rm ocr

基にするubuntuのversionを16.04にするか18.04にするかでaptで入ってくるtesseractのversionが変わり、精度が変わるので注意

結果

内部表現の発見・獲得・学習」 すなわち, さまざま
な情報が混在し, 雑音で汚れている実世界の観測情報
から, 本質的な情報やある課題 (群) に必要な情報を抽
出し, 処理しやすいように表現することは, 人工知能や
パターン認識を始めとする知的情報処理における古くか
らの研究課題の一つである. この課題に対して, これま
でにさまざまなアプローチでの研究が行われてきたが,
近年, 層の数が多い階層的なニューラルネットワーク
(deep neural network: DNN) によってデータから抽象
度の高い内部表現を獲得させる方法が, 深層学習 (deep
learning) として脚光を浴びている. そこで得られた内
部表現を用いた手法が, 一般物体認識 [Krizhevsky 121,
連続音声認識 [Dahl 12], 自然言語処理, 化合物の活性
予測, などさまざまな分野のコンペティションやベンチ
マークタスクで従来法を大きく引き離す性能をたたきだ
していることがその直接的な理由である

本気出したらめっちゃ精度ええやん

単語の位置を取得

単語ごと

プログラム

opencvとPIL同居してるけど許して…

import sys
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
import argparse

from PIL import Image
import pyocr
import cv2

def main(args: argparse.Namespace) -> None:
    tools = pyocr.get_available_tools()
    assert(len(tools) != 0)
    tool = tools[0]

    result = tool.image_to_string(
        Image.open(args.target),
        lang='jpn',
        builder=pyocr.builders.WordBoxBuilder(tesseract_layout=6)
    )

    img = cv2.imread(args.target)

    for res in result:
        print(res.position)
        print(res.content)
        cv2.rectangle(img, res.position[0], res.position[1], (0, 0, 255), 1)

    cv2.imshow('', img)
    key = cv2.waitKey(0)
    if key & 0xFF == ord('q'):
        cv2.destroyAllWindows()


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('target', type=str, help='target image')
    args = parser.parse_args()

    main(args)

結果

結果画像の一部 word.png

認識したテキスト

「 内 部 表現 の 発見 ・ 獲 得 ・ 学 習 」 すなわち , さま ざま
な 情報 が 混在 し , 雑音 で 汚れ て いる 実 世界 の 観測 情報
か ら , 本 質 的 な 情報 や ある 課題 ( 群 ) に 必要 な 情報 を 抽
出し , 処理 し や すい よう に 表現 する こと は , 人 工 知能 や
パタ ー ン 認識 を 始め と する 知 的 情報 処理 に お ける 古く か
ら の 研究 課題 の 一 つ で ある . この 課題 に 対し て , これ ま
で に さま ざま な アプ ロー チ で の 研究 が 行わ れ て きた が ,
近年 , 層 の 数 が 多い 階層 的 な ニュ ー ラ ルネ ットワーク
(deep neural network: DNN) に よっ て デー タ か ら 抽 象
度 の 高い 内 部 表現 を 獲得 させ る 方 法 が , 深層 学習 (deep
learning) と し て 脚光 を 浴び て いる . そこ で 得 ら れ た 内
部 表現 を 用 いた 手法 が , 一 般 物体 認識 [Krizhevsky 121,
連続 音声 認識 [Dahl 12], 自然 言語 処理 , 化合 物 の 活性
予測 , な ど さ ま ざま な 分 野 の コン ペティ ショ ン や ベン チ
マー クタ スク で 従来 法 を 大 きく 引き 離す 性 能 を た た きだ
し て いる こと が その 直接 的 な 理由 で ある .

行ごと

プログラム

18行目の

builder=pyocr.builders.WordBoxBuilder(tesseract_layout=6)

builder=pyocr.builders.LineBoxBuilder(tesseract_layout=6)

に書き換え

結果

結果画像の一部 line.png

テキスト

「 内 部 表現 の 発見 ・ 獲 得 ・ 学 習 」 すなわち , さま ざま
な 情報 が 混在 し , 雑音 で 汚れ て いる 実 世界 の 観測 情報
か ら , 本 質 的 な 情報 や ある 課題 ( 群 ) に 必要 な 情報 を 抽
出し , 処理 し や すい よう に 表現 する こと は , 人 工 知能 や
パタ ー ン 認識 を 始め と する 知 的 情報 処理 に お ける 古く か
ら の 研究 課題 の 一 つ で ある . この 課題 に 対し て , これ ま
で に さま ざま な アプ ロー チ で の 研究 が 行わ れ て きた が ,
近年 , 層 の 数 が 多い 階層 的 な ニュ ー ラ ルネ ットワーク
(deep neural network: DNN) に よっ て デー タ か ら 抽 象
度 の 高い 内 部 表現 を 獲得 させ る 方 法 が , 深層 学習 (deep
learning) と し て 脚光 を 浴び て いる . そこ で 得 ら れ た 内
部 表現 を 用 いた 手法 が , 一 般 物体 認識 [Krizhevsky 121,
連続 音声 認識 [Dahl 12], 自然 言語 処理 , 化合 物 の 活性
予測 , な ど さ ま ざま な 分 野 の コン ペティ ショ ン や ベン チ
マー クタ スク で 従来 法 を 大 きく 引き 離す 性 能 を た た きだ
し て いる こと が その 直接 的 な 理由 で ある .

Docker

Dokerfile

from ubuntu:18.04

MAINTAINER masataka.hisasue <masataka.hisasue@optim.co.jp>

RUN apt update && \
    apt install -y libtesseract-dev tesseract-ocr tesseract-ocr-jpn python3 python3-pip libsm6 libxext6 && \
    pip3 install pyocr opencv-python

COPY main.py /
COPY hoge.png /

CMD ["python3", "main.py", "hoge.png"]

ビルド

docker build -t ocr_box .

実行

docker run -it --rm -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix ocr_box