Распознавание символов без нейросети.

МЕНЮ


Искусственный интеллект
Поиск
Регистрация на сайте
Помощь проекту

ТЕМЫ


Новости ИИРазработка ИИВнедрение ИИРабота разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика

Авторизация



RSS


RSS новости

Новостная лента форума ailab.ru


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

Интернета у меня тогда ещё не было. Из двух статей в научно-популярных журналах я узнал про нейросети и решил, что понял как они устроены. :) Решил создать свой проект, который написал в среде Delphi 7.

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

В этой статье опишу принцип работы той программы

Подготовка изображения

1. Изображение символа подаётся в программу в виде монохромного черно-белого изображения для этого в программе есть специальный поле ввода.

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

2. Первым делом, когда изображение попала в программу, программа обрезает её со всех сторон он чтоб символ касался краёв изображения.

3. На следующем шаге изображение сжимается/растягивается отдельно по ширине и высоте, чтобы стать размером 120 на 120 пикселей.

Получение сигнатуры

4. Затем изображение делится на квадратики со стороной по 10 пиксель. В итоге изображение получается разбито на 144 квадрата (12 на 12 квадратов).

5. На следующем шаге подсчитывается количество черных пикселей в каждом квадратике и записываться в таблицу. Так как каждый квадратик имеет 100 пиксель (10х10), то таблица будет заполнена числами от 0 до 100.

6. После того как заполнили таблицу, мы ищем максимальное число в таблице. Этому числу присваивается значение 8. Относительная этого числа рассчитываются значения и для других клеток и им присваивается значение от 1 до 8. То есть, была таблица с числами от 0 до 100, стала таблица с числами от 1 до 8. Это своего рода защита от разной толщины линий, которыми нарисован символ. Если линия проходит прямо по квадрату, то в таблице будет записано число 8, в независимости, 20 или 100 пикселей были чёрными.
Выбор диапазона от 1 до 8 сейчас мне кажется странным, лучше от 0 до 7, это как раз укладывается в 3 бита, но с низкоуровневым программированием я тогда знаком не был.

У нас получилось сигнатура с которой теперь будем работать.

Распознание.

База данных программы как раз и представляет собой набор подобных сигнатур, подписанных символом которые они представляют.

Когда изображение попадают в программу и создается сигнатура, то это сигнатура сравнивается со всеми сигнатурами в базе данных.

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

На рисунке я изобразил, как вычисляется "непохожесть" двух сигнатур, уменьшенных до 9 ячеек.

Собственно и всё.

некоторые мысли

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

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

Минимальная разница между сигнатурами - 0, максимальная 7*144=1008.

Есть некоторые мысли про улучшение. Минус, точка и вертикальная линия ( - | . ) после второго пункта алгоритма (обрезка) будут представлять из себя практически полностью закрашенное черным изображение, отличить их друг от друга будет невозможно.

Нужно добавить при обрезке, что бы высота и ширина полученного изображения не отличалась более чем в два раза. Получится вот такой результат для символа "минус".

Это я не подправил программу. Если ширина символа сильно больше высоты, то алгоритм обрезки глючит и не обрезает сверху и снизу. Таким образом глюк улучшил качество распознания :). Количество несовпадений равно нулю.

Сравнение с нейросетью.

В отличие от нейросети этот алгоритм обучается очень быстро. Достаточно нарисовать один раз символ и она его начинает уже опознавать. Вторым важным моментом является то что количество распознаваемых символов здесь не ограничено. Можно бесконечно добавлять новые символы. Нейросеть изначально проектируют на определенное количество символов, под определённое количество выходов. Добавить новый символ уже проблематично.

Итоги.

Не думаю, что я изобрёл что то новое. Алгоритм напрашивается сам собой и предполагаю, что где-нибудь он давно используется.

Я поиграл с программой и нашёл некоторые косяки.

Если нет базы, то программа выдает ошибки. Нужно создать базу и закрыть программу, после чего работает корректно.

Иногда не корректно отображает содержимое базы.

Есть пункты, при каком количестве несовпадений добавлять сигнатуру в базу, а при каком модифицировать уже похожую. По умолчанию там стоят модифицировать - 80 и добавить - 160. По логике должно быть так:

  • если меньше 80, ничего делать не надо
  • если от 80 до 160 - модифицировать
  • более 160 - добавить в базу

Но программа уже добавляет в базу, если несовпадений более 80.

Исправить нет возможности, так как Delphi 7 не установлен.

Исходники.

Исходники, как есть. Я в них не разбирался, возможно что то лишнее. Есть даже небольшая справка по коду. Насколько помню, на этом проекте я разбирался с объектно-ориентированном программированием.

Исходники + исполнительный файл.


Источник: zen.yandex.ru

Комментарии: