Пользователь
0,0
рейтинг
16 августа 2009 в 14:36

Взлом каптчи файлообменника

Введение



В данной статье коротко рассказывается о процессе взлома captcha с ifolder.ru. Применение в процессе языка Python и сторонних библиотек. Применение алгоритма преобразований Хафа в составе библиотеки Open Computer Vision © Intel позволит нам избавиться от шума на изображении, простая в использовании и быстрая библиотека FANN (Fast Artificial Neural Network) сделает возможным применение искусственной нейронной сети для задачи распознавания образа.

Моя мотивация состояла, прежде всего, в том, чтобы попробовать язык Python. Как известно, лучший способ изучить язык — решить на нём какую-нибудь прикладную задачу. Поэтому параллельно описанию процесса обработки изображения я буду рассказывать о том, какие библиотеки и для чего я использовал.

Обзор проблемы



Имеем следующий вид captcha:

ifolder.ru это файлообменник, который при скачивании и закачивании хочет удостовериться в том, что вы не робот. Ресурс был взят потому, что я давно хотел применить нижеописанный алгоритм преобразований Хафа к данной задаче.

В чём трудности распознавания данной captcha? Их несколько, опишем их в порядке влияния на сложность решения задачи:

1. Наличие пересечений символов. Наглядный пример таких случаев:

Процент таких случаев относительно невелик, поэтому мы их записываем в брак с пометкой «распознаванию не подлежит».

2. Наличие линий. На каждом изображении имеются 4 линии разной длины(причём длина может быть эквивалентна линейным элементам распознаваемых объектов), толщины и угла наклона. Их мы рассматривает как главный элемент шума, от которого придётся избавляться.

3. Большой разброс в расположении символов на изображении. Символы расположены на разном уровне, на разном расстоянии.

4. Поворот символов. Символы имеют наклон по одной оси, но не более, чем на ~30 градусов (величина получена эмпирически).

5. Плавающий размер и толщина символов.

С виду достаточно простая captcha при более детальном изучении не такая уж и простая. :) Но всё не так плохо. Let’s start.

Этап 1. Создание обучающей выборки и препроцессинг



Начнём с того, что скачаем с сайта несколько сотен образцов captcha, скажем 500. Этого хватит для того, чтобы отработать алгоритмы и составить первичную обучающую выборку для нашей нейронной сети.
С помощью библиотеки urllib и незамысловатого скрипта, мы скачиваем n-ое количество необходимых образцов с сайта. После чего конвертируем их из gif в 8битный bitmap, именно с таким форматом мы продолжим работу. Важным моментом является инверсия изображения. Т.е. белые объекты на чёрном фоне. Позже будет понятно, зачем это.

Скрипт, который осуществляет всё вышеописанное:
from urllib2 import urlopen
from urllib import urlretrieve
from PIL import Image, ImageOps, ImageEnhance
import os
import sys
import re
import time
 
def main(url, n):
    # get url session url
    data = urlopen(url).read()
    match = re.search(r"/random/images/\?session=[a-z0-9]+\", data)
    if match:
   imgurl = "ifolder.ru" + match.group()
    else:
   return -1
 
    # gen imgs
    for i in range(n):
        urlretrieve(imgurl, '/test/' + str(i) + '.gif')
        time.sleep(1)
        print str(i) + ' of ' + str(n) + ' downloaded'
 
    # convert them
    for i in range(n):
        img = Image.open('/test/' + str(i) + '.gif').convert('L')
        img = ImageOps.invert(img)
        img = ImageEnhance.Contrast(img).enhance(1.9)
        img.save('/test/' + str(i) + '.bmp')
        #os.unlink('/test/' + str(i) + '.gif')
 
 
if __name__ == "__main__":
    url = sys.argv[-1]
    if not url.lower().startswith("http"):
        print "usage: python dumpimages.py http://ifolder.com/?num"
        sys.exit(-1)
    main(url, 500)


Этап 2. Удаление шума, локализация и разделение объектов.



Самый интересный и трудоёмкий этап. Примеры captcha, что я показал в обзоре, мы возьмём за образец в данной статье и будем работать с ними дальше. Итак, после первого этапа мы имеем следующее:


Для работы с изображениями я пользовался библиотеки PIL. Простая в использовании как тяпка, но достаточно функциональная и очень удобная библиотека.

Вернёмся к нашим баранам. В данном случае под шумом я подразумеваю линии.
В качестве решения проблемы я вижу несколько вариантов:
1. Генетические алгоритмы.
2. Преобразования Хафа. Можно рассматривать как разновидность автоматической векторизации.

ГА освещались на Хабре несколько раз, в том числе в процессе решения схожей задачи по взлому captcha Яндекса. Не составит труда написать модификацию генетического алгоритма для детекта прямых линий.

Тем не менее, я сделал выбор в пользу второго алгоритма. По сравнению с ГА, преобразования Хафа являются математически более строгим и детерминированным алгоритмом, в котором нет влияния случайного фактора. В данном случае он менее ресурсоёмок, в тоже время достаточно прост для понимания и применения.
Кратко, смысл алгоритма заключается в том, что любая прямая на плоскости может быть задана двумя переменными – углом наклона и расстоянием от начала координат (theta, r). Эти переменными можно рассмотреть как признаки, они формируют своё собственное двумерное пространство. Поскольку прямая есть совокупность точек и каждой из них соответствует своя пара признаков (theta, r), то в пространстве этих признаков мы будем иметь скопления точек (максимумы или peaks на пересечении) в пределах конечных окрестностей признаков соответствующие точкам прямой на исходной плоскости(изображении). Но всё проще, чем кажется. :)
Более подробно можно прочитать в Википедии и посмотреть визуализацию работы алгоритма здесь. Сразу станет ясно о чём речь.

Писать реализацию самостоятельно естественно лень. К тому же она есть в библиотеке OpenCV, с которой я достаточно часто работаю на С/С++. Есть биндинги для Python’a, которые легко собираются и устанавливаются.

В целом OpenCV достаточно низкоуровневая библиотека и работать с ней на питоне не очень удобно, поэтому авторы предусмотрели adaptors для преобразования в формат объектов PIL. Делается это очень просто:

src = cvLoadImage('image.bmp'1) # OpenCV object
pil_image = adaptors.Ipl2PIL(src) # PIL object


Процедура удаления линий выглядит следующим образом:
def RemoveLines(img):
    dst = cvCreateImage( cvGetSize(img), IPL_DEPTH_8U, 1 )
    cvCopy(img, dst)
    storage = cvCreateMemStorage(0)
    lines = cvHoughLines2( img, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/18035353 )
    for line in lines:
        cvLine( dst, line[0], line[1], bgcolor, 20 )
    return dst


Изображения должны быть монохромными, значащие пиксели белыми. Именно поэтому мы инвертировали изображение на первом этапе и будем инвертировать при распознавании.
Ключевым моментом является вызов функции cvHoughLines2. Следует обратить внимание на параметр CV_HOUGH_PROBABILISTIC, который означает применение более «умной» модификации алгоритма. Три последних параметра так же очень важны, они отражают: количество попавших точек в ячейку пространства признаков; минимальную длину линии; и максимальный пробел (gap), т.е. количество пропущенных пикселей на линии. Подробнее в документации к библиотеке.
Очень важно правильно подобрать эти параметры, иначе мы удалим с изображения прямые являющиеся частью символов или наоборот оставим много шума. Я считаю, что подобранные мною параметры являются оптимальными, но далеко не идеальными. Давайте, например, в два раза увеличим максимальный gap. Это приведёт к такому эффекту:


Вместе с линиями мы удалили много полезной информации. В тоже время правильно подобранные параметры позволяют достичь приемлемого результата:



Вы уже заметили, что, поскольку, линии часто пересекают символы, мы неизбежно удаляем и полезную информацию тоже. Это не смертельно, частично мы сможем её восстановить позже и в конечном счёте всё будет зависеть от того насколько хорошо обучена наша нейронная сеть.

Следующая задача это локализация и разделение символов. Здесь возникают проблемы, описанные в пунктах 1 и 3 в обзоре. Плавающее положение символов и поворот не позволяют нам опираться на единые координаты и расположение. Символы часто «соприкасаются», что мешает нам применить какой-нибудь алгоритм из серии contours detection.
Ясно, что делить надо по вертикали. Недолго думая, посчитаем количество белых пикселей в каждом столбце изображения и отобразим их в окне:



Чтобы построить графики я использовал библиотеку matplotlib. Библиотека поражает своей гибкостью и заложенным функционалом, ничего подобного на других языках не встречал. В качестве front-end GUI использовался PyQt4.

Если соотнести графики с изображением, то видно наличие 3х локальных минимумов. По ним и будем «обрезать» изображение. Оптимальный алгоритм поиска минимумов в данном случае трудно придумать, если он вообще есть. Поэтому мною был реализован простой алгоритм поиска локального минимума, параметры получены эмпирически, и он далеко не оптимален. Это важный момент и более продуманный алгоритм может существенно повысить качество распознавания.
Процедуру разделения изображения на символы вы можете найти в исходниках(FindDividingCols и DivideDigits).

Далее мы обрезаем символы т.к. остаётся много фоновой области. После можно попытаться восстановить потерянную полезную информацию. Могу посоветовать применить морфологические алгоритмы, например Erosion & Dilation (Эрозия и Дилатация) или Closing (Замыкание). Их можно найти в библиотеке OpenCV, пример использования на питоне есть в репозитории библиотеки — OpenCV\samples\python\morphology.py. Все полученные изображения отдельных символов приводятся к единому размеру 18х24.

Результат разделения на символы:


Этап 3. Распознавание



Следующий этап это создание нейросети и её обучение. Из 500 изображений (по 4 символа на каждом) я получил меньше 1000 образцов приемлемого качества и содержания использованных для обучения. Если мы обучим сеть до уровня распознавания одного символа с вероятностью 0.5, то получим общую эффективность 0.5^4 = 0.0625 или 6%. Цель более, чем достижима. Полученной выборки для неё хватило. Если у вас есть желание поработать «китайцем» несколько дней, то велика вероятность добиться лучших результатов, тут главное терпение, которого у меня нет. :)
Для создания и использования нейросетей удобно использовать библиотеку FANN. Wrapper для питона без напильника никак собираться не хотел, пришлось править код полученный SWIG’ом. Я решил выложить скомпилирированную библиотеку, инсталлер для питона 2.6 и несколько примеров использования. Скачать можно здесь. Я написал небольшие инструкции по установке, смотрите INSTALL.

На вход подаём массив из 18*24 = 432 пикселей (точнее передаём 1 если пиксель значащий и 0 если фон), на выходе получаем массив из 10 чисел, каждый из которых отражает вероятность принадлежности входного массива к тому или иному классу (цифре). Таким образом входной слой нашей нейросети состоит из 432 нейронов, выходной из 10. Создаётся ещё один скрытый слой с числом нейронов == 432 / 3.

Код для создания и обучения сети:
from pyfann import libfann
 
num_input = 432
num_output = 10
num_layers = 3
num_neurons_hidden = 144
desired_error = 0.00006
max_epochs = 50000
epochs_between_reports = 1000
 
ann = libfann.neural_net()
 
ann.create_standard(num_layers, num_input, num_neurons_hidden, num_output)
ann.set_activation_function_hidden(libfann.SIGMOID_SYMMETRIC_STEPWISE)
ann.set_activation_function_output(libfann.SIGMOID_SYMMETRIC_STEPWISE)
 
ann.train_on_file('samples.txt', max_epochs, epochs_between_reports, desired_error)
 
ann.save('fann.data')
ann.destroy()


Использование:
def MagicRegognition(img, ann):
    ann = libfann.neural_net()
    ann.create_from_file('fann.data')
 
    sample = []
    for i in img.size[1]:
        for j in img.size[0]:
            if colordist(img.getpixel((j, i)), bgcolor) < 10:
                sample[j + i * img.size[0]] = 0
            else:
                sample[j + i * img.size[0]] = 1
 
    res = ann.run(sample)
 
    return res.index(max(res))


Заключение



Python великолепный язык, очень лаконичный и красивый, с множеством сторонних библиотек, которые покрывают все мои повседневные потребности. Низкий порог вхождения, во многом благодаря солидному сообществу и количеству документации. Питонщики, теперь я с вами ;)

Дополнительные библиотеки, которые использовались:
NumPy
SciPy

Исходники (mirror 1, mirror 2)

Для подстветки синтаксиса использовался ресурс highlight.hohli.com.

UPD: 1. Перезалил исходники на 3 ресурса. 2. По просьбе, из файла dumpimages.py убрал три последних символа в регулярном выражении для ссылки на каптчу на странице ifolder. А то «дети» балуются :)

Indalo @Indalo
карма
181,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое

Комментарии (68)

  • –62
    Ломать не строить
    • +61
      На самом деле к captcha это не относится. Т.к. сделать сложную captcha гораздо проще, чем разработать алгоритм распознавания.
      • +2
        Капчи существуют только для того, что бы их кто-то взламывал)
      • +1
        В этом и есть смысл капчи =)
    • +1
      в случае капчи уместнее сказать: строить — не ломать :)
  • +11
    Статьи про распознавание как всегда очень познавательные. Пишите еще
    • +28
      Возможно следующая статья будет по детекту объектов (машина, лицо, оружие) на изображении с применением алгоритмов boosting'a
      • +1
        Очень-очень интересно)
        • –2
          И мне, и мне! :)
  • +1
    Так каков процент распознавания?
    • +1
      простите за невнимательность. нашел в статье
  • +3
    Почитал статью, решился все-таки попробовать «по питонить». Спасибо.
    • НЛО прилетело и опубликовало эту надпись здесь
      • +1
        точняк =)
  • +1
    В распознавании образов алгоритмы на основе нейронных сетей использовались давно, и показали себя с хорошей стороны. Распознавание каптчи — абсолютно та же задача распознания образов. В связи с этим разгадывание каптчи ботами — лишь вопрос времени распространения алгоритмов нейронных сетей среди веб-программистов. Так что пора использовать более продвинутую защиту, в которой для решения задачи недостаточно входных параметров, а также требуется интеллект. Например мне нравится защита вопрос-ответ при большой базе вопросов, разумеется.
    • +5
      Большая — сколько? Допустим 1000 пар вопрос-ответ (попробуйте ещё придумайте хотя-бы столько!). Тогда распознавальщику достаточно будет знать 60 пар чтобы получить те-же 6% эффективности. А это гораздо проще, чем распознать капчу.
      • +3
        Согласен. Вопрос-ответ конечно не выстоит, если его специально будут подбирать. Но он вполне для малопосещаемых ресурсов — форумов, персональных страниц. Попробуйте поставить форум phpbb3 самой последней версии с каптчей — на нем в первый же день появятся боты. Почему? Потому потому что каптча повсюду и по инету гуляют спамерские боты, которые щелкают капчти как орехи. А вопрос-ответ не популярен (по-моему его вобще нигде нет). Пытался ставить различные каптчи на свои проекты (менял алгоритм формирования картинок) и все равно всегда некоторый процент ботов проходил. После установки вопрос-ответ — ни единого бота. Ну конечно, повторюсь, мои сайты никто специально не подбирал, посещаемость у них 100-150 человек и мало кому нужно их ломать, но от примитивных спамеров обезопасился.

        Сложную защиту с интеллектом я пока не разрабатывал, если будут идеи, отпишусь. Я вобщем не продвигал вопрос-ответ как панацею, а лишь сказал, что в задаче подбора должно не хватать входных данных. В каптче вот все входные данные на картинке. Нужно только подстроить под нее нейронную сеть и прогнать. А вопрос-ответ это задача, в которой требуются «знания», т.е. что-то помимо самого вопроса.
        • 0
          > Сложную защиту с интеллектом я пока не разрабатывал, если будут идеи, отпишусь.

          Как вариант, можно отображать свои вопросы в виде несильно зашумленной капчи.
          Только чтобы не в формате bmp ))
        • 0
          Варианты — «выберите 3 изображения живой природы» (видел в работе — довольно интересно) либо «укажите картинку, на которой изображен такой-то предмет»

          • +1
            Только эффективность у них не высокая. Все упирается в размер базы таких картинок.
            Но у такого типа каптч есть будущее, если научится генерировать картинки автоматически.
        • +2
          Ну, знаете, когда у вас народу мало, можно их вообще капчами не мучать. Достаточно в клиенте джаваскриптом вычислять какую-то функцию, а на сервере проверять. Если функцию сделать не тривиальную и обернуть её пакером, то желающих не много найдется разбираться в этом коде. Я так делал для одного сайта — вполне нормально защищало (ни одного пробоя).
          • 0
            А я в скрытый средствами css div — включал поле «ConfirmEmail». Боты его старательно заполняют, а люди — нет. www.recoilme.ru/register/register_form
          • +1
            > Ну, знаете, когда у вас народу мало, можно их вообще капчами не мучать. Достаточно в клиенте джаваскриптом вычислять какую-то функцию, а на сервере проверять.

            Ммм, не сказал бы, что все так просто. Часто встречаются роботы на основе браузеров :)
            Знаете систему тестирования SeleniumRC (http://seleniumhq.org/projects/remote-control/)? Вот на ее основе можно спамеру делать ботов и жить припеваючи.

            Основная моя мысль — что каптча задача устаревшая, надо придумывать что-то другое, причем что-то, где требуются «мозги». Вот например с картинками — шаг в эту сторону. Роботу нужно уметь сопостовлять изображения и понятия — это уже «кусок» искусственного интеллекта.
            Кстати если думать совсем абстрактно о далеком будущем, то с изобретением искусственного интеллекта борьба со спамом станет невозможным :D
        • +1
          > и все равно всегда некоторый процент ботов проходил
          Это наверняка был спам вручную. Некоторые спаммеры даже начинают разговаривать в комментах, если их потравить. Обижаются. Школьникам летом нечего делать, вот и занимаются «SEO».
    • 0
      > лишь вопрос времени распространения алгоритмов нейронных сетей среди веб-программистов
      Так и представляю толпы студентов прочитавших Пых-Пых за 21 день и ломающих каптчу.
      Не будет этого. Возможно появятся библиотеки заточеные под конкретные виды каптчи, но масового не будет потому что образовательный уровень масы веб-разработчиков в части математики и обработки сигналов нулевой, а без него даже простую каптчу не разпознаешь.
      Основная маса разработчиков «Где найти библиотеку на Пых-Пых которая делает то-то».
      • 0
        Основная маса разработчиков «Где найти библиотеку на Пых-Пых которая делает то-то».

        в мое время самым популярным вопросам было «где найти компонент для дельфи» :-)
        • 0
          вопросом, конечно же. Миль пардон, милостивые судари.
  • 0
    И ведь не поленились же вы написать.)
    Вообще подобный материал очень увлекателен. Я года 4 назад изучал труды нейронных сетей Кохонена и тогда не хватало примера для наглядности. Теперь и на моей улице праздник =)
    Спасибо.
  • 0
    Спасибо, очень познавательно.
  • –1
    Сегодня обнаружил в качалке jDownloader возможности распознания капч.
    • 0
      о, спасибо. чую нужная вещь.
  • 0
    > Кратко, смысл алгоритма заключается в том, что любая прямая на плоскости может быть задана двумя переменными – углом наклона и расстоянием от начала координат (theta, r)

    Может, Любая точка а не прямая? Идея мне понравилась, перевод в другую систему координат :) Оригинально!
    • 0
      Через эту точку может быть проведено множество прямых.

      Одна прямая конечно задана быть не может.
      • 0
        Ну так я и пишу что это точка задан 2 координатами :) Для прямой надо минимум 4 я догадываюсь.
        • 0
          Почему же? Хватит и двух координат — угол наклона прямой (в примере из статьи — от вертикали считается) и длины перпендикуляра от центра координат (начала, левый верхний там же) до прямой.
          • 0
            Ой, туплю, в смысле для отрезка надо 4 координаты :)
          • 0
            >в примере из статьи — от вертикали считается

            Лучше трактовать не как угол между прямой и осью ординат, а как угол между нормалью и осью абсцисс.
  • +1
    Дождался новой серии, спасибо)
    Вам впору написать книжку, посвященную подобным вещам) Наверняка будет классикой для интересующихся)
  • +1
    Так чем дело-то кончилось, удалось добиться распознавания или нет?

    После всех статей про распознавание CAPTCHA неизменно возникает вопрос: какая CAPTCHA, на ваш взгляд, самая стойкая?
    Как со стойкостью, к примеру, у ReCAPTCHA?
    • +1
      Удалось. Обученую нейросеть выкладывать не стал. Кто заинтересовался сможет воспроизвести результат.

      Помнится на рапидшаре была каптча с котятами и собачками. Там я с 5го раза угадывал :)
      • 0
        Вот например такая:

        habrahabr.ru/ blogs/php/28151/
    • +1
      Насколько я знаю у рекапчи всё хорошо. Они используют базу слов, которые заведомо не осилило OCR при оцифровке старых книг. В любом случае нужно понимать, что чем популярнее защита, тем больше желающих её сломать. Лучше использовать свои методы :)
      • +1
        Хороший повод для развития OCR. Оцифровщики книг будут рады тому, кто сделает прорыв в этой области :-)
  • 0
    Спасибо большое! Черезвычайно интересно!
  • +3
    А исходники скачали только первые 10 счастливчиков?
    • +2
      надо было выкладывать на iFolder, ага
  • 0
    Перезалейте, s'il vous plaît.
  • 0
    очень круто и увлекательно. спасибо.
  • 0
    Автору большой респект за подробно расписанное сообщение :)
    читать легко и приятно, так же как программировать на Python!
  • 0
    Полгода назад тоже писал подобное только без нейросетей, алгоритм был следующим:
    Разделение -> очистка и векторизация символов -> нахождение наиболее похожих в базе.

    Правда забросил это дело, возможно если исходники разищу тоже выложу.
    • 0
      Было бы замечательно. Особенно интересны разделения сложных «слипшихся» символов. Да и по векторизации материал не будет лишним.
      • 0
        В крайнем случае по памяти попробую восстановить, там ничего сложного не было:

        Разделял примерно так же как и здесь (данные о предварительном разделении сохранялись для последующего откидывания помеховых линий).
        Потом просто откидывались ровные длинные линии (>1 знака или явно выходящие за рамки основного текста), а при векторизации бралась любая точка и от нее просматривало периметр(при перегибе более вероятным считался плавный изгиб), отметки о наличии точки писались как угол, потом это все склеивалось(т.е. проход в одну и другую сторону).

        Хотел еще вероятностную карту создавать по типу (Ж60%; Ш90%; Щ95%), а пртом сверять по словарю на чем и забросил это дело.
  • +1
    Хороший подход.
  • 0
    > На вход подаём массив из 18*24 = 432 пикселей (точнее передаём 1 если пиксель значащий и 0 если фон), на выходе получаем массив из 10 чисел

    Вот никогда не понимал. Массив из 432 пикселей линейный? Нейросетка никак не знает, что каждые 18 пикселей «пристыковываются» снизу? Если так, то результат будет весьма посредственный. А если не так, то объясните, каким образом нейросетка рассматривает двумерное изображение действительно как двумерное изображение?

    > Создаётся ещё один скрытый слой с числом нейронов == 432 / 3.

    Что означает это число? Из каких соображений взято?
    • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      1. Не знает и ей не надо. Если вас научить таким последовательностям:

      100 — человек
      101 — кошка
      110 — собака

      Потом вы сможете «распознавать» эти объекты по «кодам» :) Только наш мозг не в состоянии воспринять 432 бита, а искусственной нейросети всё равно сколько бит.

      2. Если упрощённо, то промежуточный слой берётся для того, чтобы сеть сходилась более плавно, что повышает устойчивость сети. Число получено эмпирически. Единого ответа на вопрос «сколько брать скрытых слоёв и сколько ставить нейронов», насколько мне известно, не существует.
      • 0
        > 1. Не знает и ей не надо. Если вас научить таким последовательностям:
        > 100 — человек
        > 101 — кошка
        > 110 — собака
        > Потом вы сможете «распознавать» эти объекты по «кодам» :) Только наш мозг не в состоянии воспринять 432 бита, а искусственной нейросети всё равно сколько бит.

        Вы сейчас говорите о линейных цифровых образах. Такие образы да, хорошо обрабатываются нейросеткой с линейным входом. А мы говорим о распознавании символов, которые являются двумерными объектами.

        Я слабо разбираюсь в нейросетях, но мне представляется, что для хорошего распознавания двумерных объектов нужна двумерная нейросетка (а существует ли такие?).

        Либо исходное изображение символа надо переводить в какое-то промежуточное представление, которое «транслирует» объект из двумерного представления в естественное для такого объекта одномерное представление. Например, букву «A» можно написать обычным образом, сильно вытянутым, наклонным, изогнутым. Если, например смотреть на «А» сверху вниз, то как бы не была написана буква, можно сказать что образ описывается по строкам

        пусто
        пусто, точка, пусто
        пусто, точка, пусто, точка, пусто
        пусто, линия, пусто
        пусто, точка, пусто, точка, пусто
        пусто

        далее по вертикальным строкам тоже самое. Таким образом, двумерное представление преобразовано в линейное, сохранив совокупную информацию об образе не в виде разрозненных пикселей, а в виде взаимосвязей между основными точками и линиями. Понятно, что для одной буквы «A» может быть несколько «преобразованных» таким (или подобным) методом образов. Но нейросетку надо обучать именно на таких данных, а не просто на наборе абстрактных нулей и единиц (что тоже впринципе даст результат).

        Вообще думаю, что как минимум, нужно каким-то образом рассказать нейросетке какой размер в пикселях по вертикали и горизонтали имеется, что бы как-то сбалансировать связи между соседними точками в одной строке и в одном столбце.
  • 0
    Ура! Кто теперь сделает скрипт для greasemonkey? :)
  • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Очень интересно. Спасибо за статью.
  • 0
    Вся проблема каптчей в том, что мы пытаемся программно с генерировать нечто, что программно бы не взламывалось…
    • 0
      Какая же в этом проблема то? Асимметричное шифрование вполне себе живо.
      • 0
        Ассиметричное шифрование в смысле MD5 хэширование и тому подобное?
        • 0
          Асимметричное шифрование в смысле криптография с открытым ключом.
  • 0
    Кто успел скачать FANN, может перезалить куда-нибудь? Или Indalo.
    • 0
      Обновил ссылку.
  • 0
    Картинки поломались :(
  • 0
    ann = libfann.neural_net()

    ann.create_standard(num_layers, num_input, num_neurons_hidden, num_output)
    ann.set_activation_function_hidden(libfann.SIGMOID_SYMMETRIC_STEPWISE)
    ann.set_activation_function_output(libfann.SIGMOID_SYMMETRIC_STEPWISE)

    ann.train_on_file('samples.txt', max_epochs, epochs_between_reports, desired_error)


    — В каком месте тут идет обучение ни как не пойму?
    — Где входные данные для обучения и желаемый результат?
    — Или они в фале «samples.txt» — тогда поясните пожалуйста, что мне туда писать?

    Сразу столько вопросов, потому что во многих статьях пишется одно и тоже, и пока никто не собрался силой описать процедуру обучения.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.