본문 바로가기

DeepLearning/OCR_

[OCR] CRNN Model_기본 구조

반응형

<CRNN모델의 backbone역할을 하는 model에 대한 function>

  • backbone 역할을 하는 함수 : 논문에서 언급한 대로 VGG-16 모델 구현해서 사용.

  • CNN Layer + LSTM(RNN) Layer
  • CNN Layer의 마지막의 2개의 Fully-Connected Layer 층은 CNN층으로 변경한다

  • RNN부분에서 LSTM을 사용하고 싶으면 gru=False로 주고, GRU를 사용할 때는 gru=True

 

1> CRNN parameter

- Input_shape : ( 256, 32, 1 )

- num_classes : 87 --> 라벨로 사용되는 클래스 수

 

2> CRNN Model output_shape : (학습과 예측의 모델이 각각 존재한다)

    Model Architecture : CNN(6) + RNN(LSTM)(2) + FC(1) + Activation(softmax) = x 

    - model_train : Model(inputs=[image_input, labels, input_length, label_length], outputs=ctc_loss)

                           >> output shape : ( None, 1 )

                           >> 학습 모델의 경우 인풋인자가 4개로 늘어나고, 아웃풋 값이 ctc_loss를 적용한 값이 나온다.

 

    model_pred Model(image_input, x) 

                           >> Model의 output은 softmax를 통과하고 나온다. 

                           >> output shape : ( None, 62, 87 )

 

 

3> Model.summary() : 각각 모델에서 공통으로 가지는 부분(model_prediction과 동일)

    >> Input : ( None, 256, 32, 1 ) : (샘플 갯수, width, height, channel)

    >> Conv1_1 * MaxPooling : ( None, 128, 16, 64 ) : 128 * 16 크기의 feature map 64개 생성

    >> Conv2_1 * MaxPooling : ( None, 64, 8, 128) : 64 * 8 크기의 feature map 128개 생성

    >> Conv3_1 * Conv3_2 * MaxPooling : ( None, 64, 4, 256) : 64 * 4 크기의 feature map 256개 생성

    >> Conv4_1 * BatchNormalization ( None, 64, 4, 512) : 64 * 4 크기의 feature map 512개 생성

    >> Conv5_1 * BatchNormalization * MaxPooling( None, 64, 2, 512) : 64 * 2 크기의 feature map 512개 생성

    >> Conv6_1 : ( None, 62, 1, 512 )64 * 1 크기의 feature map 512개 생성

    >> Reshape : ( None, 62, 512 ) : reshape(-1, 512)로 모양을 변경한다.

    >> Bidirectional LSTM * Bidirectional LSTM : ( None, 62, 512 )  

    >> Dense : (None, 62, 87)

    >> Softmax : (None, 62, 87) 

 

 

**위의 기본 구조는 model_prediction 할 때 사용하고,

Model_Train 시킬 경우에는 기존 이미지 인풋에 3개의 인풋이 더 추가되고 아웃풋 값이 ctc loss 로 바뀐다.

아래에 차례로 2개의 모델의 summary()를 참고

 

 

 

< Model_Train >

위 모델 구조는 model_training에 사용되는 구조이다.

 

<Model_prediction>

위 모델 구조는 model_prediction에 사용되는 구조이다.

 

4> 실제 모델 코드

ssd_detectors / crnn_model.py
def CRNN(input_shape, num_classes, prediction_only=False, gru=False):
    """CRNN architecture.
    
    # Arguments
        input_shape: Shape of the input image, (256, 32, 1).
        num_classes: Number of characters in alphabet, including CTC blank.
        
    # References
        https://arxiv.org/abs/1507.05717
    """
    
    act = 'relu'
    
    # KERAS API를 사용한 모델 구현
    x = image_input = Input(shape=input_shape, name='image_input')
    
    x = Conv2D(64, (3, 3), strides=(1, 1), activation=act, padding='same', name='conv1_1')(x)
    x = MaxPool2D(pool_size=(2, 2), strides=(2, 2), name='pool1', padding='same')(x)
    
    x = Conv2D(128, (3, 3), strides=(1, 1), activation=act, padding='same', name='conv2_1')(x)
    x = MaxPool2D(pool_size=(2, 2), strides=(2, 2), name='pool2', padding='same')(x)
    
    x = Conv2D(256, (3, 3), strides=(1, 1), activation=act, padding='same', name='conv3_1')(x)
    x = Conv2D(256, (3, 3), strides=(1, 1), activation=act, padding='same', name='conv3_2')(x)
    x = MaxPool2D(pool_size=(2, 2), strides=(1, 2), name='pool3', padding='same')(x)
    
    x = Conv2D(512, (3, 3), strides=(1, 1), activation=act, padding='same', name='conv4_1')(x)
    x = BatchNormalization(name='batchnorm1')(x)
    
    x = Conv2D(512, (3, 3), strides=(1, 1), activation=act, padding='same', name='conv5_1')(x)
    x = BatchNormalization(name='batchnorm2')(x)
    x = MaxPool2D(pool_size=(2, 2), strides=(1, 2), name='pool5', padding='valid')(x)
    
    x = Conv2D(512, (2, 2), strides=(1, 1), activation=act, padding='valid', name='conv6_1')(x)
    x = Reshape((-1,512))(x)
    
    if gru:
        x = Bidirectional(GRU(256, return_sequences=True))(x)
        x = Bidirectional(GRU(256, return_sequences=True))(x)
    
    else:
        x = Bidirectional(LSTM(256, return_sequences=True))(x)
        x = Bidirectional(LSTM(256, return_sequences=True))(x)
    
    x = Dense(num_classes, name='dense1')(x)
    
    # output은 softmax함수를 사용하여 라벨에대한 확률값이 나온다.
    x = y_pred = Activation('softmax', name='softmax')(x)
    
    #모델을 정의 : Model(input, output)
    model_pred = Model(image_input, x)
    
    # train모델이아닌 preiction 모델의 output은 softmax activation을 적용한 값
    if prediction_only:
        return model_pred

    #최대 글자수
    max_string_len = int(y_pred.shape[1])

    # CTC LOSS 함수 정의
    def ctc_lambda_func(args):
        labels, y_pred, input_length, label_length = args
        return K.ctc_batch_cost(labels, y_pred, input_length, label_length)

    # CTC LOSS를 계산할때 사용하는 INPUT 정의
    labels = Input(name='label_input', shape=[max_string_len], dtype='float32')
    input_length = Input(name='input_length', shape=[1], dtype='int64')
    label_length = Input(name='label_length', shape=[1], dtype='int64')

    # Lambda를 사용하여 ctc loss 구한다
    ctc_loss = Lambda(ctc_lambda_func, output_shape=(1,), name='ctc')([labels, y_pred, input_length, label_length])
    
    # 최종 학습모델의 인풋은 4가지이고, 아웃풋은 ctc loss 값
    model_train = Model(inputs=[image_input, labels, input_length, label_length], outputs=ctc_loss)
    
    return model_train, model_pred
    
반응형