Распознавание капчи с «живым» CNN

машинное обучение искусственный интеллект TensorFlow глубокое обучение Нейронные сети
Распознавание капчи с «живым» CNN

1 Знакомство с проверочным кодом

Код подтверждения (CAPTCHA) — общедоступная, полностью автоматическая программа, которая различает, является ли пользователь компьютером или человеком. В тесте CAPTCHA компьютер, выступающий в роли сервера, автоматически генерирует вопрос, на который должен ответить пользователь. Этот вопрос может сгенерировать и оценить компьютер, но ответить на него может только человек. Поскольку компьютеры не могут отвечать на вопросы CAPTCHA, пользователь, который отвечает на вопрос, может считаться человеком.

2 Введение в распознавание кода проверки CNN

Традиционный метод состоит в том, чтобы выполнить распознавание текста с помощью двух не связанных шагов: 1) найти положение текста на картинке, а затем использовать «маленькую рамку» для сегментации и вырезать текст на картинке 2) и затем выполнить идентификацию . Однако в современном распознавании проверочного кода, когда текст на распознаваемом изображении становится рукописным и накладывается друг на друга, этот метод «сегментации» трудно использовать. Поэтому сверточные нейронные сети (CNN) используются для распознавания этих необъяснимых почерков. Эта CNN состоит из одного или нескольких сверточных слоев и полностью связанного слоя наверху (соответствующего классической нейронной сети) для распознавания изображений. Для обучения модели обучения CNN требуется большое количество аннотированных вручную изображений, но метод, описанный в этой статье, заключается в независимой генерации случайных символов и создании соответствующих изображений для настройки параметров во время работы. В этой статье основное внимание уделяется изображениям капчи с 4 символами. Каждый символ представлен как 62 нейрона в выходном слое. Мы можем предположить функцию отображения

x \in  \lbrace 0’...'9','A'...'Z','a'...'z'\rbrace

вести переписку

l \in \lbrace0...61\rbrace

который:

\Theta(x)=\begin{cases}0...9 &  x ='0'...'9'\\10...35 &  x = 'A'...'Z'\\36...61 &  x = 'a'...'z' \end{cases}

Первые 62 нейрона назначаются первому символу в последовательности, а вторая партия из 62 нейронов назначается второму символу в последовательности. Следовательно, для символа xi

Индекс соответствующего нейрона

n = i * 62 + \Theta(x_i)  i \in \lbrace 0...3 \rbrace

Всего имеется 4*62=128 выходных слоев. Если индекс первого предсказанного символа равен c0=52, то предсказанный символ можно обратить как

x = \Theta^-1(c0) =q

3 этапа реализации

1 Генерация проверочного кода

1 символ в капче

number = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
ALPHABET = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
            'V', 'W', 'X', 'Y', 'Z']
alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
            'v', 'w', 'x', 'y', 'z']

gen_char_set = number + ALPHABET  # 用于生成验证码的数据集

2 символа для генерации кода подтверждения

  # char_set=number + alphabet + ALPHABET,
        char_set=gen_char_set,
        # char_set=number,
        captcha_size=4):
    """
    生成随机字符串,4位
    :param char_set:
    :param captcha_size:
    :return:
    """
    captcha_text = []
    for i in range(captcha_size):
        c = random.choice(char_set)
        captcha_text.append(c)
    return captcha_text

3 Сгенерируйте соответствующий проверочный код в соответствии с символами

def gen_captcha_text_and_image():
    """
    生成字符对应的验证码
    :return:
    """
    image = ImageCaptcha()

    captcha_text = random_captcha_text()
    captcha_text = ''.join(captcha_text)

    captcha = image.generate(captcha_text)

    captcha_image = Image.open(captcha)
    captcha_image = np.array(captcha_image)
    return captcha_text, captcha_image

4 тренировки

def crack_captcha_cnn(w_alpha=0.01, b_alpha=0.1):
    """1
    定义CNN
    cnn在图像大小是2的倍数时性能最高, 如果你用的图像大小不是2的倍数,可以在图像边缘补无用像素。
    np.pad(image,((2,3),(2,2)), 'constant', constant_values=(255,))  # 在图像上补2行,下补3行,左补2行,右补2行
    """

    x = tf.reshape(X, shape=[-1, IMAGE_HEIGHT, IMAGE_WIDTH, 1])

    # w_c1_alpha = np.sqrt(2.0/(IMAGE_HEIGHT*IMAGE_WIDTH)) #
    # w_c2_alpha = np.sqrt(2.0/(3*3*32))
    # w_c3_alpha = np.sqrt(2.0/(3*3*64))
    # w_d1_alpha = np.sqrt(2.0/(8*32*64))
    # out_alpha = np.sqrt(2.0/1024)

    # 3 conv layer
    w_c1 = tf.Variable(w_alpha * tf.random_normal([3, 3, 1, 32]))
    b_c1 = tf.Variable(b_alpha * tf.random_normal([32]))
    conv1 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(x, w_c1, strides=[1, 1, 1, 1], padding='SAME'), b_c1))
    conv1 = tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
    conv1 = tf.nn.dropout(conv1, keep_prob)

    w_c2 = tf.Variable(w_alpha * tf.random_normal([3, 3, 32, 64]))
    b_c2 = tf.Variable(b_alpha * tf.random_normal([64]))
    conv2 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv1, w_c2, strides=[1, 1, 1, 1], padding='SAME'), b_c2))
    conv2 = tf.nn.max_pool(conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
    conv2 = tf.nn.dropout(conv2, keep_prob)

    w_c3 = tf.Variable(w_alpha * tf.random_normal([3, 3, 64, 64]))
    b_c3 = tf.Variable(b_alpha * tf.random_normal([64]))
    conv3 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv2, w_c3, strides=[1, 1, 1, 1], padding='SAME'), b_c3))
    conv3 = tf.nn.max_pool(conv3, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
    conv3 = tf.nn.dropout(conv3, keep_prob)

    # Fully connected layer
    w_d = tf.Variable(w_alpha * tf.random_normal([8 * 20 * 64, 1024]))
    b_d = tf.Variable(b_alpha * tf.random_normal([1024]))
    dense = tf.reshape(conv3, [-1, w_d.get_shape().as_list()[0]])
    dense = tf.nn.relu(tf.add(tf.matmul(dense, w_d), b_d))
    dense = tf.nn.dropout(dense, keep_prob)

    w_out = tf.Variable(w_alpha * tf.random_normal([1024, MAX_CAPTCHA * CHAR_SET_LEN]))
    b_out = tf.Variable(b_alpha * tf.random_normal([MAX_CAPTCHA * CHAR_SET_LEN]))
    out = tf.add(tf.matmul(dense, w_out), b_out)  # 36*4
    # out = tf.reshape(out, (CHAR_SET_LEN, MAX_CAPTCHA))  # 重新变成4,36的形状
    # out = tf.nn.softmax(out)
    return out

Из-за нехватки времени и оборудования я удалил английские буквы из строки генерации проверочного кода и оставил только цифры для обучения. В противном случае можно рассчитать, что показатель точности по-прежнему составляет 3%. На следующем рисунке показан тренировочный скриншот результата обучения более 10 000 шагов gen_char_set = число + АЛФАВИТ.

5 Резюме

В этой статье «живая CNN» используется для распознавания проверочного кода, что может сэкономить много ручных шагов маркировки и значительно повысить эффективность работы.


Текст / JoeCDC

любитель математики

Монтаж/Флуоресценция

Автор разрешил опубликовать эту статью, и авторские права принадлежат Chuangyu Frontend. Пожалуйста, укажите источник для перепечатки этой статьи. Ссылка на эту статью:известно Sec-Fed.com/2018-09-28-…

Если вы хотите подписаться на другие сообщения с передовой линии KnownsecFED, выполните поиск и подпишитесь на нашу общедоступную учетную запись WeChat: KnownsecFED. Добро пожаловать, чтобы оставить сообщение для обсуждения, мы ответим как можно скорее.

Спасибо за чтение.