web-dev-qa-db-ja.com

私自身のOCRプログラムPython

私はまだ初心者ですが、文字認識プログラムを書きたいと思っています。このプログラムはまだ準備ができていません。そして、私はたくさん編集したので、コメントが正確に一致しないかもしれません。連結成分のラベリングには8接続を使用します。

from PIL import Image
import numpy as np

im = Image.open("D:\\Python26\\PYTHON-PROGRAMME\\bild_schrift.jpg")

w,h = im.size
w = int(w)
h = int(h)

#2D-Array for area
area = []
for x in range(w):
    area.append([])
    for y in range(h):
        area[x].append(2) #number 0 is white, number 1 is black

#2D-Array for letter
letter = []
for x in range(50):
    letter.append([])
    for y in range(50):
        letter[x].append(0)

#2D-Array for label
label = []
for x in range(50):
    label.append([])
    for y in range(50):
        label[x].append(0)

#image to number conversion
pix = im.load()
threshold = 200
for x in range(w):
    for y in range(h):
        aaa = pix[x, y]
        bbb = aaa[0] + aaa[1] + aaa[2] #total value
        if bbb<=threshold:
            area[x][y] = 1
        if bbb>threshold:
            area[x][y] = 0
np.set_printoptions(threshold='nan', linewidth=10)

#matrix transponation
ccc = np.array(area) 
area = ccc.T #better solution?

#find all black pixel and set temporary label numbers
i=1
for x in range(40): # width (later)
    for y in range(40): # heigth (later)
        if area[x][y]==1:
            letter[x][y]=1
            label[x][y]=i
            i += 1

#connected components labeling
for x in range(40): # width (later)
    for y in range(40): # heigth (later)
        if area[x][y]==1:
            label[x][y]=i
            #if pixel has neighbour:
            if area[x][y+1]==1:
                #pixel and neighbour get the lowest label             
                pass # tomorrows work
            if area[x+1][y]==1:
                #pixel and neighbour get the lowest label             
                pass # tomorrows work            
            #should i also compare pixel and left neighbour?

#find width of the letter
#find height of the letter
#find the middle of the letter
#middle = [width/2][height/2] #?
#divide letter into 30 parts --> 5 x 6 array

#model letter
#letter A-Z, a-z, 0-9 (maybe more)

#compare each of the 30 parts of the letter with all model letters
#make a weighting

#print(letter)

im.save("D:\\Python26\\PYTHON-PROGRAMME\\bild2.jpg")
print('done')
27
kame

OCRは確かに簡単な作業ではありません。そのため、テキストCAPTCHAは引き続き機能します:)

パターン認識ではなく文字抽出についてのみ話すために、文字を分離するために使用している手法は 連結成分ラベリングと呼ばれます。 -) 。これを行うためのより効率的な方法を求めているので、この記事で説明されている2パスアルゴリズムを実装してみてください。別の説明は、記事 ブロブ抽出 にあります。

[〜#〜] edit [〜#〜]:これが私が提案したアルゴリズムの実装です:

import sys
from PIL import Image, ImageDraw

class Region():
    def __init__(self, x, y):
        self._pixels = [(x, y)]
        self._min_x = x
        self._max_x = x
        self._min_y = y
        self._max_y = y

    def add(self, x, y):
        self._pixels.append((x, y))
        self._min_x = min(self._min_x, x)
        self._max_x = max(self._max_x, x)
        self._min_y = min(self._min_y, y)
        self._max_y = max(self._max_y, y)

    def box(self):
        return [(self._min_x, self._min_y), (self._max_x, self._max_y)]

def find_regions(im):
    width, height  = im.size
    regions = {}
    pixel_region = [[0 for y in range(height)] for x in range(width)]
    equivalences = {}
    n_regions = 0
    #first pass. find regions.
    for x in xrange(width):
        for y in xrange(height):
            #look for a black pixel
            if im.getpixel((x, y)) == (0, 0, 0, 255): #BLACK
                # get the region number from north or west
                # or create new region
                region_n = pixel_region[x-1][y] if x > 0 else 0
                region_w = pixel_region[x][y-1] if y > 0 else 0

                max_region = max(region_n, region_w)

                if max_region > 0:
                    #a neighbour already has a region
                    #new region is the smallest > 0
                    new_region = min(filter(lambda i: i > 0, (region_n, region_w)))
                    #update equivalences
                    if max_region > new_region:
                        if max_region in equivalences:
                            equivalences[max_region].add(new_region)
                        else:
                            equivalences[max_region] = set((new_region, ))
                else:
                    n_regions += 1
                    new_region = n_regions

                pixel_region[x][y] = new_region

    #Scan image again, assigning all equivalent regions the same region value.
    for x in xrange(width):
        for y in xrange(height):
                r = pixel_region[x][y]
                if r > 0:
                    while r in equivalences:
                        r = min(equivalences[r])

                    if not r in regions:
                        regions[r] = Region(x, y)
                    else:
                        regions[r].add(x, y)

    return list(regions.itervalues())

def main():
    im = Image.open(r"c:\users\personal\py\ocr\test.png")
    regions = find_regions(im)
    draw = ImageDraw.Draw(im)
    for r in regions:
        draw.rectangle(r.box(), outline=(255, 0, 0))
    del draw 
    #im.show()
    output = file("output.png", "wb")
    im.save(output)
    output.close()

if __name__ == "__main__":
    main()

そして、これが出力ファイルです:

デッドリンク

100%完璧というわけではありませんが、これは学習目的でのみ行っているため、出発点として適している場合があります。各文字のバウンディングボックスを使用すると、他の人がここで提案しているように、ニューラルネットワークを使用できます。

34
jbochi

OCRは非常に難しいです。コンピュータで生成された文字であっても、フォントとフォントサイズを事前に知らないと、非常に困難です。文字を正確に一致させているとしても、私はそれを「最初の」プログラミングプロジェクトとは呼びません。それは非常に微妙です。

スキャンされた文字や手書きの文字を認識したい場合は、さらに難しくなります。高度な数学、アルゴリズム、機械学習を使用する必要があります。このトピックについて書かれた本や記事はかなりたくさんあるので、車輪の再発明をする必要はありません。

私はあなたの努力に感心しますが、あなたはまだ実際の困難にぶつかるのに十分な距離に達していないようです。これまでのところ、ピクセルをランダムに探索し、ある配列から別の配列にコピーしています。あなたはまだ実際に比較をしていません、そして私はあなたの「ランダムウォーク」の目的がわかりません。

  • なぜランダムなのですか?正しいランダム化アルゴリズムを書くことは非常に困難です。最初に決定論的アルゴリズムから始めることをお勧めします。
  • なぜある配列から別の配列にコピーするのですか?直接比較してみませんか?

比較するときは、画像が「プロトタイプ」とまったく同じではないという事実に対処する必要があり、それをどのように処理するかが明確ではありません。

ただし、これまでに作成したコードに基づいて、私はあなたにアイデアを持っています。画像の「迷路」を通り抜けるプログラムを作成してみてください。入力は、画像に加えて、開始ピクセルと目標ピクセルになります。出力は、スタートからゴールまでの迷路を通るパスです。これはOCRよりもはるかに簡単な問題です-迷路を解くことはコンピューターにとって素晴らしいことです-しかしそれでも楽しくてやりがいがあります。

7
dmazzoni

最近のほとんどのOCRアルゴリズムは、ニューラルネットワークアルゴリズムに基づいています。 ホップフィールドネットワーク 開始するのに適した場所です。利用可能なホップフィールドモデルに基づいて ここではC 、私はpythonあなたが説明したものと同様の非常に基本的な画像認識アルゴリズムを構築しました。完全なソースを投稿しました- ここ 。これはおもちゃのプロジェクトであり、実際のOCRには適していませんが、正しい方向に進むことができます。

ホップフィールドモデルは、ビットマップ画像のセットを保存および呼び出すへの自動関連付けメモリとして使用されます。画像は、対応する重み行列を計算することによって保存されます。その後、任意の構成から開始して、メモリはハミング距離の点で開始構成に最も近い、その保存された画像に正確に落ち着きます。したがって、保存された画像の不完全または破損したバージョンが与えられると、ネットワークは対応する元の画像を呼び出すことができます。

A Javaアプレットからおもちゃの例を見つけることができます ここ ;ネットワークは0〜9の数字の入力例でトレーニングされています。右側のボックスに描画します、[テスト]をクリックして、ネットワークからの結果を確認します。

数学表記に脅かされないでください。ソースコードに到達すると、アルゴリズムは単純になります。

5
J.J.

OCRは非常に難しいです! OCRを試行するために使用するアプローチは、達成しようとしていること(手書きの認識、コンピューターで生成されたテキストの読み取りなど)に基づきます。

ただし、開始するには、ニューラルネットワークとOCRを確認してください。これは、このテーマに関するいくつかのすぐに使える記事です。

http://www.codeproject.com/KB/cs/neural_network_ocr.aspx

http://www.codeproject.com/KB/dotnet/simple_ocr.aspx

お気に入りの検索エンジンを使用して情報を見つけます。

楽しんで!

4
tgiphil