見出し画像

Pythonで画像の文字認識をしたい話


はじめに

 とある作品を作るために、画像から文字を抽出したいので、備忘録として残しておきます。
 画像を認識し、文字列をターミナルに戻すことを目標とします。

環境構築

OCRを使う環境構築

 調べてみると、python単体で文字認識をすることはできないので、OCR(光学的文字認識)のエンジンをpythonで制御するみたいです。

 まず、OCRエンジンのTesseract OCRを導入します。

環境変数にパスを通しておきましょう。()

C:\Program Files\Tesseract-OCR

このURL(https://github.com/tesseract-ocr/tessdata/blob/main/jpn.traineddata)に日本語の学習データがあるので、ダウンロードして、

C:\Program Files\Tesseract-OCR\tessdata

上のフォルダにいれておいてください。

Tesseract-OCRを使う為に、pytesseractをインストールします。

pip install pytesseract

今回の環境

Python 3.11
    pillow 10.2.0
    pytesseract 0.3.10
Tesseract-OCR 5.3.3

 pillowが無かったら、インストールしておいてください。今回は上記の環境で動作させていきます。

画像処理のプログラム

簡単な画像の文字認識

 下のような、白黒で文字の綺麗な画像を用意しました。

sample.png

この画像を読み込んでTesseract-OCRを実行するように、以下のコードを作成しました。

import pytesseract
from PIL import Image

class charRec:
    def __init__(self):
        #画像の読み込み 
        self.img = Image.open(r"画像のパス\sample.png").convert("RGB")

    def imgText(self):
        #Tesseract -OCRの実行
        return pytesseract.image_to_string(self.img, lang="jpn")

img = charRec()
result = img.imgText()
print(result)

pillowで画像を読み込み、RGB形式に変換し、Tesseract-OCRの実行結果を返します。

実行結果

こ ん に ち は 。 テ ス ト で す .
隣 の 宣 は よ く 柿 食 う 客 だ 。

 このような結果になりました。
柿を宣と間違えていますね。しかしそのほかは認識しているので、精度はそれなりに高いですね。

複雑な画像の文字認識

 免許証の画像認識をやってみます。使用する画像は警視庁のホームページにある見本を使わせていただきます。

license.jpg
出典:https://www.npa.go.jp/policies/application/license_renewal/index.html

とりあえず実行してみましょう。

① 日 生

g⑥① キ ⑤ 月

不

①E

②

が 関 ② ー ①

区 霞

⑫③④⑤

る 和 0 ① 年 0 ⑤ 月 0⑦ B

( 磁

せ 所 | 東 京 都 千 代

付

a

あまり認識できていませんね。精度をあげることを目標にしましょうか。

認識の精度をあげる

学習データの差し替え

Tesseract-OCRの学習データは、精度重視のものがあるらしいので差し替えてみます。
tessdata_best/jpn.traineddata at main · tesseract-ocr/tessdata_best · GitHub
tessdata_best/jpn_vert.traineddata at main · tesseract-ocr/tessdata_best · GitHub
これで実行してみました。

1 日 生

昭和 61 年 5 月

子

人 花

2

が 関 2ー1

区 震

12345

令 和 01 年 05 月 07 晶

( 品

住所 | 東京 都 千 代

付

数字の精度が著しく良くなっています。漢字の変換もよくなっていますね。
住所までしか読みとらないのは認識する文字数の問題でしょうか。なにはともあれ次です。

画像を読み取りやすくする。

 文字を認識するための画像なら、文字以外は消したほうがいいと思うので、処理していきましょう。

def Convert(self):
    width,height = self.img.size
    for x in range(width):
        for y in range(height):
            r, g, b = self.img.getpixel((x,y))

            if r >= 59 and g >= 59 and b >= 59:
                self.img.putpixel((x,y),(255,255,255))

上記は黒の濃さが一定以下のピクセルを全て白色に置き換えるメソッドです。下は変換した画像です。

変換後のlicense.jpg

上の文字が切れてますが、真ん中の太いけど色がついていた部分などははっきりと見れるようになってますね。
 出力結果は以下のようになります。

1 日生

昭和 61 年 om

時

ー2

1

各局 い

双 mp
05107 ヨ

京都 千代

令 和
2024 析 信和 06 旬 06 有 1H ま で

12345

01

堆 。

限 境 等

見

中

* 引 第 U12345678900 wu

下の部分が読み取られているのが見て取れます。これ以外に自身の学生証でもとりましたが、モノクロ部分だけを読み取るのでしたら、最初にグレースケールに変換してもいいかもしれません。

最後に

 今回作成したコードです。

import pytesseract
from PIL import Image

class charRec:
    def __init__(self):
        self.img = Image.open("画像パス").convert("RGB")

    def Convert(self):
        width,height = self.img.size
        for x in range(width):
            for y in range(height):
                r, g, b = self.img.getpixel((x,y))

                if r >= 59 and g >= 59 and b >= 59:
                    self.img.putpixel((x,y),(255,255,255))

        self.img.save("保存パス")

    def imgText(self):
        return pytesseract.image_to_string(self.img, lang="jpn")

image = charRec()
image.Convert()
result = image.imgText()
print(result)

 画像の読み込みと、一定値以上に白いピクセルは真っ白にして、Tesseract-OCRを実行させるというプログラムです。
 今回は実験しながら書いたので、画像を読み込むタイミングが早いです。
今後このコードを使う場合は、コンソールで指定できるようにするといいかもしれません。また文字が切れたら補完できるようにしたいですね。

この記事が気に入ったらサポートをしてみませんか?