web-dev-qa-db-ja.com

OpenCVを使用したTesseract OCRの前処理画像

Tesseractを使用して、携帯電話のカムで撮影されたドキュメントのテキストを認識するアプリを開発しようとしています。 OpenCVを使用して画像を前処理して認識を向上させ、ガウスぼかしと2値化にしきい値法を適用していますが、結果はかなり悪いです。

ここ は、テストに使用している画像です。 enter image description here

そして ここ 前処理された画像: enter image description here

Tesseractで画像を読みやすくするために使用できる他のフィルターは何ですか?

22
Mauricio

ここでは、Tesseractの画像を準備するためのいくつかのヒントについて説明しました。 tesseractを使用してナンバープレートを認識する

あなたの例では、いくつかのことが起こっています...

テキストを黒にし、残りの画像を白にする必要があります(not逆)。それが文字認識が調整されているものです。グレースケールisは、背景がほぼ完全に白で、テキストがほぼ完全に黒である限り、問題ありません。テキストのエッジは灰色(アンチエイリアス)であり、そのmayは認識に役立ちます(ただし、必ずしもそうではありません-実験する必要があります)

表示される問題の1つは、画像の一部ではテキストが実際に「薄い」(しきい値処理後に文字のギャップが表示される)一方で、他の部分では実際に「太い」(および文字が始まる)マージ)。 Tesseractはそれを気に入らないでしょう:)入力画像が均等に照らされていないため、単一のしきい値がどこでも機能しないために起こります。解決策は、画像の各隣接について異なるしきい値が計算される「局所適応しきい値処理」を行うことです。それを行うには多くの方法がありますが、例えばチェックアウトしてください:

あなたが持っている別の問題は、線が直線ではないということです。私の経験では、Tesseractは非常に限られた程度の非直線のライン(遠近法の歪み、傾斜またはスキューの数パーセント)を処理できますが、 tはwavy行で実際に動作します。可能であれば、ソース画像に直線があることを確認してください:)残念ながら、これに対する簡単な既製の答えはありません。研究文献を調べて、最先端のアルゴリズムの1つを自分で実装する必要があります(可能であれば、それをオープンソースにします。これに対するオープンソースソリューションが本当に必要です)。 Google Scholarで「 曲線OCR抽出 」を検索すると、開始できます。例:

最後に、C++のOpenCVよりもpythonエコシステム(ndimage、skimage)を使用する方がはるかに良いと思います。OpenCVpythonラッパーは大丈夫ですシンプルなものですが、あなたがやろうとしていることは役に立たないので、OpenCVにない多くのピースを取得する必要があります(もちろん、組み合わせることができます)。 C++は、python(* pythonを知らなくても当てはまります)の場合よりも1桁長い時間がかかります。

がんばろう!

45
Alex I
  1. 300 dpi(1インチあたりのドット数)でのスキャンは、公式にはOCR(光学式文字認識)の標準ではありませんが、ゴールドスタンダードと見なされています。

  2. 画像をグレースケールに変換すると、一般的なテキストの読み取り精度が向上します。

Imageのテキストを読み取り、OCRから最適な結果を得るために画像を処理するモジュールを作成しました Image Text Reader

import tempfile

import cv2
import numpy as np
from PIL import Image

IMAGE_SIZE = 1800
BINARY_THREHOLD = 180

def process_image_for_ocr(file_path):
    # TODO : Implement using opencv
    temp_filename = set_image_dpi(file_path)
    im_new = remove_noise_and_smooth(temp_filename)
    return im_new

def set_image_dpi(file_path):
    im = Image.open(file_path)
    length_x, width_y = im.size
    factor = max(1, int(IMAGE_SIZE / length_x))
    size = factor * length_x, factor * width_y
    # size = (1800, 1800)
    im_resized = im.resize(size, Image.ANTIALIAS)
    temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.jpg')
    temp_filename = temp_file.name
    im_resized.save(temp_filename, dpi=(300, 300))
    return temp_filename

def image_smoothening(img):
    ret1, th1 = cv2.threshold(img, BINARY_THREHOLD, 255, cv2.THRESH_BINARY)
    ret2, th2 = cv2.threshold(th1, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    blur = cv2.GaussianBlur(th2, (1, 1), 0)
    ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    return th3

def remove_noise_and_smooth(file_name):
    img = cv2.imread(file_name, 0)
    filtered = cv2.adaptiveThreshold(img.astype(np.uint8), 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 41,
                                     3)
    kernel = np.ones((1, 1), np.uint8)
    opening = cv2.morphologyEx(filtered, cv2.MORPH_OPEN, kernel)
    closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel)
    img = image_smoothening(img)
    or_image = cv2.bitwise_or(img, closing)
    return or_image
14
Amit Kushwaha

注:これは私が答えるアレックスへのコメントである必要がありますが、長すぎるので答えとしてそれを置きます。

「Tesseract OCRエンジンの概要、Google Inc.レイ・スミス」 https://github.com/tesseract-ocr/docs/blob/master/tesseracticdar2007.pdf

「処理は従来の段階的なパイプラインに従いますが、一部の段階は当時は珍しく、現在でもそうである可能性があります。最初のステップは、コンポーネントのアウトラインが保存される接続コンポーネント分析です。これは当時は計算コストが高い設計決定でしたが、大きな利点がありました:アウトラインのネスト、および子と孫のアウトラインの数を検査することにより、反転テキストを検出し、白黒テキストと同じくらい簡単に認識できます。Tesseractは、おそらく黒地に白のテキストを非常に簡単に処理できる最初のOCRエンジンでした。」

だから、白い背景に黒いテキストを置く必要はないようで、反対に動作するはずです。

5
AndrewBloom