簡體   English   中英

使用Keras進行無分段的手寫文本識別

[英]Segmentation-free Handwritten Text Recognition with Keras

我目前正在開發一種無分段手寫文本識別的應用程序。 因此,從輸入文檔中提取了文本行,然后應將其識別出來。

出於開發目的,我使用了IAM手寫數據庫 它提供文本行圖像以及相應的ASCII文本。

為了進行識別,我采用了“ 基於圖像的序列識別的端到端可訓練神經網絡及其在場景文本識別中的應用 ”和“ 我們可以使用LSTM網絡構建獨立於語言的OCR嗎? ”中找到的方法。

從根本上講,我使用雙向GRU體系結構和正向后退算法來使成績單與神經網絡的輸出對齊。

來自數據庫的圖像如下所示: 在此處輸入圖片說明

圖像以像素值的一維序列表示,更准確地說,首先將圖像縮放到32個像素的高度。
上面圖像的numpy數組的尺寸為597 x 32,其形狀為:(597,32)。
表示大小為n的整體訓練圖像的numpy數組的形狀為:(n,w,32),其中w表示線圖像的可變寬度(例如597)。

以下代碼顯示了訓練圖像和轉錄的表示方式:

x_train = []
y_train = []
line_height_normalized = 32
for i in range(sample_size):
    transcription_train, image_train = self._get_next_sample()
    image_train = convert_to_grayscale(image_train)
    image_train = scale_y(image_train, line_height_normalized)
    image_train_patches = sklearn_image.extract_patches_2d(image_train, (line_height_normalized, 1))   
    image_train_patches = numpy.reshape(image_train_patches, (image_train_patches.shape[0], -1))
    x_train.append(image_train_patches)
    y_train.append(transcription_train)

我使用Keras,並基於此示例創建遞歸神經網絡和CTC函數。

charset = 68
number_of_memory_units = 512
time_steps = None
input_dimension = 32  # the height of a text line in pixel

# input shape see https://github.com/keras-team/keras/issues/3683
network_input = Input(name="input", shape=(time_steps, input_dimension))  

gru_layer_1 = GRU(number_of_memory_units, return_sequences=True, kernel_initializer='he_normal',
                  name='gru_layer_1')(network_input)
gru_layer_1_backwards = GRU(number_of_memory_units, return_sequences=True, go_backwards=True,
                  kernel_initializer='he_normal',name='gru_layer_1_backwards')(network_input)
gru_layer_1_merged = add([gru_layer_1, gru_layer_1_backwards])
gru_layer_2 = GRU(number_of_memory_units, return_sequences=True, kernel_initializer='he_normal',
                  name='gru_layer_2')(gru_layer_1_merged)
gru_layer_2_backwards = GRU(number_of_memory_units, return_sequences=True, go_backwards=True, kernel_initializer='he_normal',
                  name='gru_layer_2_backwards')(gru_layer_1_merged)

output_layer = Dense(charset, kernel_initializer='he_normal',
                  name='dense_layer')(concatenate([gru_layer_2, gru_layer_2_backwards]))
prediction = Activation('softmax', name='output_to_ctc')(output_layer)

# create the ctc layer
input_length = Input(name='input_length', shape=[1], dtype='int64')
label_length = Input(name='label_length', shape=[1], dtype='int64')
max_line_length = 200  # see QUESTION 1
labels = Input(name='labels', shape=[max_line_length], dtype='float32')
loss_out = Lambda(RecurrentNeuralNetwork._ctc_function, name='ctc')(
        [prediction, labels, input_length, label_length])
model = Model(inputs=[network_input, labels, input_length, label_length], outputs=loss_out)

sgd = SGD(lr=0.02, decay=1e-6, momentum=0.9, nesterov=True, clipnorm=5)
model.compile(loss={'ctc': lambda l_truth, l_prediction: prediction}, optimizer=sgd)

問題1
在示例中,使用了max_line_length 正如我在互聯網上閱讀的(但我認為我不太理解它退出得很好)一樣,由於底層CTC函數需要知道應創建多少張量,因此需要最大行長。
可變的行長適合什么長度,這對看不見的文本行的識別有何影響?
此外, input_length變量以及label_length變量准確表示什么?

在下一步中,對網絡進行訓練:

batch_size = 1  
number_of_epochs = 4 

size = 32  # line height? see QUESTION 2
input_length = numpy.zeros([size, 1])
label_length = numpy.zeros([size, 1])
for epoch in range(number_of_epochs):
    for x_train_batch, y_train_batch in zip(x_train, y_train_labels):
        x_train_batch = numpy.reshape(x_train_batch, (1, len(x_train_batch), 32))
        inputs = {'input': x_train_batch, 'labels': numpy.array(y_train_batch),
                      'input_length': input_length, 'label_length': label_length}
        outputs = {'ctc': numpy.zeros([size])}  # dummy data for dummy loss function
        self.model.fit(x=inputs, y=outputs, batch_size=batch_size, epochs=1, shuffle=False)
        self.model.reset_states()

由於時間步長是可變的(文本行的寬度),因此按大小為1的批次進行訓練。
文本行的轉錄由numpy數組y_train_batch表示 每個字符都用數字編碼。
上面的圖像示例的抄錄如下所示:

[26 62 38 40 47 30 62 19 14 62 18 19 14 15 62 38 17 64 62 32  0  8 19 18 10  4 11 11 62  5 17 14 12]   

問題2
size變量代表什么? 是信號圖像塊的尺寸,從而是每個時間步的特征嗎?

錯誤
發生的錯誤如下:

  • 預期標簽的形狀為(200,),但數組的形狀為(1,)
    是否需要填充標簽數組以包含200個元素?

當我將max_line_length的值替換為1時,會發生下一個錯誤:

  • 所有輸入數組(x)都應具有相同數量的樣本。 得到的數組形狀:[(1,597,32),(33,1),(32,1),(32,1)]
    是否有必要重塑其他三個陣列?
    我不確定解決此問題的“正確”方法是什么,以及接下來可能發生的錯誤?

也許有人可以指出我正確的方向。
非常感謝你!

好的,我無法用注釋部分中提供的600個字符來解釋這一點,因此我將通過回答來做到這一點,而忽略了您的第二季度。

您提到的論文代碼可以在以下位置找到: https : //github.com/bgshih/crnn這是手寫文本識別的一個很好的起點。 但是,CRNN實現可以在單詞級別識別文本,而您希望在行級別識別文本,因此需要更大的輸入圖像,例如,我使用800x64px,最大文本長度為100。如上所述,將圖像拉伸到所需的大小不能很好地工作,在我的實驗中,使用填充時精度有所提高(將位置隨機化一點……這是進行數據擴充的一種簡便方法)。

最大文本長度L和輸入圖像寬度W之間存在關系:神經網絡(NN)通過固定縮放因子f縮小輸入圖像的大小:L = W / f(在我的示例中:W = 800px,L = 100,f = 8)。 隨附的插圖顯示了輸入圖像(800x64px)和字符概率矩陣(100個時間步長中的每個80個可能字符的概率)。 NN將輸入圖像映射到此字符概率矩陣,該矩陣用作CTC的輸入。 由於矩陣中有L個多個時間步長,因此最多可以有L個多個字符:這當然適用於解碼,但是損耗計算必須以某種方式將基本真值文本與此矩陣對齊,以及具有L的文本應該如何對齊+1個字符僅與矩陣中包含的L個時間步對齊! 請注意,在CTC計算中,重復字符(如“ piZZa”中的字符)必須用特殊字符分隔-因此,每次重復的可能文本長度減少1。

字符概率矩陣

我認為通過這種解釋,您應該能夠弄清楚代碼中所有這些長度變量如何相互關聯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM