Идея 1: Flood fill
Эта идея не использует 50 паттернов, которые у вас есть на цифру: она основана на идее, что обычно «1» соединяет все 0 битов вокруг этой «1»shape, в то время как «0» отделяет 0-бит внутри него от тех, что снаружи, а «8» имеет две такие закрытые области. Таким образом, подсчет соединенных областей 0-битных данных определит, какой из трех он является.
Таким образом, вы можете использовать алгоритм заливки флудом , начиная с любого 0-битного вектора, и установить всеэти соединенные 0-биты к 1. В одномерном массиве вы должны позаботиться о том, чтобы правильно идентифицировать подключенные биты (либо по горизонтали: 1 позиция друг от друга, но не пересекая 32 границы, либо вертикально ... 32 позиции друг от друга). Конечно, эта заливка уничтожит изображение, поэтому обязательно используйте копию. Если после одного такого заполнения до сих пор осталось 0 битов (которые, следовательно, не были связаны с теми, которые вы превратили в 1), выберите один из них и начните второе заполнение там. Повторите при необходимости.
Когда все биты были установлены в 1 таким образом, используйте количество выполненных вами заливок, как указано ниже:
- Одна заливка? Это «1», потому что все 0 битов связаны.
- Два заполнения? Это «0», потому что форма нуля разделяет две области (внутри / снаружи)
- Три заливки? Это «8», потому что эта форма разделяет три области соединенных 0-битов.
Конечно, этот процесс предполагает, что эти рукописные цифры хорошо сформированы. Например, если фигура 8 будет иметь небольшой разрыв, как здесь:
.. тогда она не будет обозначена как "8", но" 0 ". Эта конкретная проблема может быть решена путем определения «свободных концов» в 1 бит («линия», которая останавливается). Если у вас есть два из них на небольшом расстоянии, увеличьте число, полученное в результате подсчета заливки, на 1 (как если бы эти два конца были соединены).
Аналогично, если «0» случайно имеетмаленький второй цикл, как здесь:
... он будет обозначен как «8» вместо «0». Вы могли бы предотвратить эту конкретную проблему, потребовав, чтобы каждая заливка находила минимальное количество 0-бит (например, не менее 10 0-бит), чтобы считаться одним.
Идея 2: вектор вероятности
Для каждой цифры сложите 50 примерных векторов, которые у вас есть, так что для каждой позиции у вас будет счет от 0 до 50. У вас будет один такой вектор «вероятности» на цифру, так что prob0, prob1 и prob8. Если prob8 [501] = 45, это означает, что весьма вероятно (45/50), что вектор «8» будет иметь 1-битный индекс 501.
Теперь преобразуем эти 3 вектора вероятности следующим образом: вместо сохранения количества на позицию сохраняйте позиции в порядке уменьшения количества (вероятности). Таким образом, если prob8 [513] имеет наибольшее значение (например, 49), то этот новый массив должен начинаться как [513, ...]. Давайте назовем эти новые векторы A0, A8 и A1 (для соответствующей цифры).
Наконец, когда вам нужно сопоставить заданный входной вектор, одновременно проходите через A0, A1 и A8 (всегда просматривая один и тот же индексв трех векторах) и сохранить 3 балла. Когда входной вектор имеет 1 в положении, указанном в A0 [i], тогда прибавьте 1 к Score0. Если он также имеет 1 в позиции, указанной в A1 [i] (то же самое i ), то добавьте 1 к Score1. То же самое для Score8. Увеличьте i и повторите. Остановите эту итерацию, как только у вас будет явный победитель, т. Е. Когда наивысший балл среди оценок 0, 1 и 8 превысит пороговую разницу со вторым по величине среди них. В этот момент вы знаете, какая цифра представляется.