Понимание цепных кодов Freeman для OCR
Заметьте, что я действительно ищу ответ на свой вопрос. Я не ищет ссылку на какой-то исходный код или на какой-то академический документ: я уже использовал источник, и я уже читал документы и до сих пор не понял последнюю часть этого вопрос...
Я работаю над быстрым шрифтом OCR, и я очень хорошо продвигаюсь.
Я уже нахожу базовые линии, разделяя символы, преобразуя каждый символ в черно-белый, а затем контурируя каждый символ, чтобы применить к нему код цепи Freeman.
В основном это 8-связный код цепи выглядит следующим образом:
3 2 1
\ | /
4-- --0
/ | \
5 6 7
Итак, если у меня есть "a", после всех моих преобразований (включая преобразование в черно-белый), я получаю что-то вроде этого:
11110
00001
01111
10001
10001
01110
Тогда внешний граф может выглядеть так (я могу ошибаться здесь, что контур ASCII-art и мой "алгоритм" могут получить контур неправильно, но это не вопрос моего вопроса):
XXXX
X1111X
XXXX1X
X01111X
X10001X
X10001X
X111X
XXX
Следуя Xs, я получаю код цепи, который будет:
0011222334445656677
Обратите внимание, что нормализованный код цепи, но вы всегда можете нормализовать код цепи следующим образом: вы просто сохраняете наименьшее целое число.
(Кстати, есть суперэффективная реализация, чтобы найти код цепи, где вы просто берете 8 соседних пикселей "X", а затем смотрите в 256 таблице поиска, если у вас есть 0,1,2,3, 4,5,6 или 7).
Теперь мой вопрос: из этого кода 0011222334445656677, как найти, что у меня есть 'a'?
Потому что, например, если мой 'a' выглядит так:
11110
00001
01111
10001
10001
01111 <-- This pixel is now full
Тогда мой код цепи теперь: 0002222334445656677
И все же это также "а".
Я знаю, что вся суть этого кода цепи должна быть устойчивой к таким крошечным изменениям, но я не могу понять, как я должен найти, какой символ соответствует одному цепочному коду.
Я был так далеко, и теперь я застрял...
(Кстати, мне не нужна 100% -ная эффективность, и такие вещи, как дифференцирование "0" с "O" или "o", на самом деле не проблема)
Ответы
Ответ 1
Вам нужна функция d
, которая измеряет расстояние между цепными кодами. После того, как найти письмо с заданным кодом цепи, просто:
Input:
- нормализованные цепные коды
S
для набора возможных букв (обычно коды каина для A-Z, a-z, 0-9,...)
- код цепи
x
буквы, которая должна быть обнаружена и которая может быть слегка деформирована (код цепи не будет соответствовать коду цепи в наборе S
)
Алгоритм будет перебирать множество возможных цепочечных кодов и вычислять расстояние d(x,si)
для каждого элемента. Буква с наименьшим расстоянием будет выходом алгоритма (идентифицированная буква).
Я бы предложил следующую функцию distance:
Для двух цепных кодов добавьте разности длин в каждом направлении: d(x,si) = |x0-si0| + |x1-si1| + .. + |x7-si7|
. x0
- это число 0s в цепочном коде x
, si0
- это число 0s в цепочном коде si
и т.д.
Пример лучше объяснит, о чем я думаю. На следующем рисунке представлены буквы 8, B и D, четвертая буква - немного деформированная 8, которая должна быть идентифицирована. Буквы написаны с помощью Arial с размером шрифта 8. Вторая строка изображения увеличена в 10 раз, чтобы лучше видеть пиксели.
![enter image description here]()
Я вручную вычислил (надеюсь, правильно) нормализованные коды цепи, которые:
8: 0011223123344556756677
B: 0000011222223344444666666666
D: 00001112223334444666666666
8': 000011222223344556756666 (deformed 8)
Различия в длине (абсолют):
direction | length | difference to 8'
| 8 | B | D | 8'| 8 | B | D |
----------+---+---+---+----+-----+----+-----
0 | 2 | 5 | 4 | 4 | 2 | 1 | 0 |
1 | 3 | 2 | 3 | 2 | 1 | 0 | 1 |
2 | 3 | 5 | 3 | 5 | 2 | 0 | 2 |
3 | 3 | 2 | 3 | 2 | 1 | 0 | 1 |
4 | 2 | 5 | 4 | 2 | 0 | 3 | 2 |
5 | 3 | 0 | 0 | 3 | 0 | 3 | 3 |
6 | 3 | 9 | 9 | 5 | 2 | 4 | 4 |
7 | 3 | 0 | 0 | 1 | 2 | 1 | 1 |
----------+---+---+---+----+-----+----+-----
sum 10 | 12 | 14 |
8'
имеет наименьшее расстояние до цепного кода 8
, поэтому алгоритм идентифицирует букву 8
. Расстояние до буквы B
не намного больше, но это потому, что деформированный 8 выглядит почти как B
.
Этот метод не является масштабирующим инвариантом. Я думаю, что есть два варианта преодоления этого:
- Для разных размеров шрифтов, имеющих разные наборы нормализованных цепочечных кодов
- Один набор нормализованных цепочечных кодов большого размера (например, 35x46 пикселей) и масштабирование входной буквы (которая должна быть идентифицирована) для этого большего размера.
Я не совсем уверен, что функция расстояния достаточно хороша для набора всех буквенно-цифровых букв, но я надеюсь на это. Чтобы свести к минимуму ошибку при идентификации письма, вы можете включить другие функции (а не только коды цепочки) на этап классификации. И снова вам понадобится дистанционная мера - на этот раз для векторов признаков.
Ответ 2
Поскольку ваш вопрос недостаточно конкретный (хотите ли вы полного алгоритма, основанного на цепочном коде или просто некоторой вероятностной классификации), я расскажу вам, что я знаю о проблеме.
Используя код цепи, вы можете подсчитать некоторые свойства символа, например. число оборотов формы 344445, 244445, 2555556, 344446 (произвольное число 4s), т.е. "шипы" на букве. Скажем, в коде цепи есть 3 раздела, которые выглядят так. Итак, это почти наверняка "W"! Но это хороший случай. Вы можете подсчитывать числа разных видов вращения и сравнивать их с ранее сохраненными значениями для каждой буквы (что вы делаете вручную).
Это довольно хороший классификатор, но, конечно, этого недостаточно. Невозможно отличить "D" и "O", "V" и "U". И многое зависит от вашего воображения.
Вы должны начать с создания тестового примера изображений некоторых букв со ссылкой и проверить свой алгоритм между изменениями и изобретать новые критерии.
Надеюсь, что это ответ на ваш вопрос хотя бы частично.
Обновление:
Одна яркая идея только что пришла мне в голову:)
Вы можете подсчитать количество монотонных последовательностей в цепочке, например, для цепочки 000111222233334443333222444455544443333 (быстрый тупой пример, на самом деле не соответствует какой-либо букве), который у нас есть
00011122223333444 3333222444455544443333,
00011122223333444 3333222 444455544443333,
000111222233334443333222 4444555 44443333,
0001112222333344433332224444555 44443333,
то есть. четыре монотонные подпоследовательности.
Это должно быть хорошим обобщением, просто подсчитайте количество этих изменений для реальных букв и сравните с тем, что получено из обнаруженной цепи, это хорошая попытка.
Некоторые проблемы и идеи:
- Цепочка является циклической в некотором смысле, поэтому вам нужно иметь дело с обнаружением монотонности на концах цепочки (чтобы избежать ошибок "один за другим" ),
- Некоторые артефакты должны учитываться, например, если вы знаете, что письмо достаточно велико (например, высота 20 пикселей), вы хотели бы игнорировать прерывание монотонности менее трех элементов, например:)
Ответ 3
Вы можете преобразовать код цепи в еще более упрощенную модель, которая передает топологию, а затем запускает код машинного обучения (который, вероятно, будет записываться в Prolog).
Но я бы не стал его одобрять. Люди уже много лет пробовали это, и у нас пока нет хороших результатов.
Вместо того, чтобы тратить свое время на этот нелинейный/пороговый подход, почему бы вам просто не использовать метод надежный, основанный на корреляции? Проще всего было бы свернуться с шаблонами.
Но я бы разработал вейвлеты Габора на буквах и отсортировал коэффициенты в векторном пространстве. Погрузите векторную машину поддержки с некоторыми примерами, а затем используйте ее как классификатор.
Это в значительной степени то, как это делает наш мозг, и я уверен, что это возможно в компьютере.
Некоторые случайные chit chat (игнорировать):
Я бы не использовал нейронные сети, потому что я их не понимаю и поэтому не люблю их.
Тем не менее, меня всегда впечатляет работа группы Джефф Хинтонс http://www.youtube.com/watch?v=VdIURAu1-aU.
Как-то он работает в сетях, которые могут распространять информацию назад (глубокое обучение).
Говорит о нем, где он дает возможность узнать, что сеть узнала о знании. Это означает, что он устанавливает один из выходных нейронов в "2", и сеть будет генерировать изображения вещей, которые, по его мнению, являются двумя на входных нейронах.
Я нашел это очень круто.
Ответ 4
В прошлом месяце я имел дело с одной и той же проблемой. Теперь я решил эту проблему по цепочке цепочек ветерок.
Код цепи ветерок - это двоичный код цепи. Затем я разрезал его на 5 частей. Очевидно, что число 0-9 имеет свой собственный символ в другой части.