Бьюсь об стенку над одной задачей. Задача связанна с микроконтроллерами. Поэтому ресурсы ограничены. На входе небольшая посылка данных. Данные это набор чисел от 0 до 255. Нужно их отнести к тому или иному классу данных. Т.е. к 0 или 1. И уже на основе полученного кода сделать определенные действия. Пример: между 5-7 это 0 между 9-11 это 1 Но тут появилась одна большая проблема. В первой посылке класс А может занимать диапазон от 5-7 а уже во второй 9-11. При четком указывании диапазонов данные воспринимаются не правильно. Но всегда известно, что класс А всегда меньше класса Б. Между ними всегда есть небольшой промежуток. В посылка всегда будет присутствовать хотя бы один класс данных. ЗЫ: Проще говоря нужно обработать штрих код. Но в этом случае просто неизвестна заранее толщина линий.
В штрихкодах толстые и тонкие линии обычно образуют группы с одинаковым количеством толстых и тонких линий(например 5 тонких и 3 толстые). То есть можно просто найти среднюю толщину линий и использовать это число в качестве границы. Еще можно получив первое число установить две контрольные точки, одну к примеру на 40%(зависит от соотношения толщины линий) больше полученного числа, а вторую меньше. И пока числа не выйдут за этот диапазон, считаем что они принадлежат к одному классу(можно даже обновлять точки по последнему полученному числу), а как только получим число за пределеми этого диапазона, то сможем однозначно определить где проходит граница.
Да, походу придется использовать в начале кода контрольную линию. Например первая всегда толстая и относительно нее дальше ориентироваться. Хотя это не особо мне нравиться. Капец. Смотря на числа определяю точно где 0 а где 1. Но даже не представляю как это описать.
a9d Еще можно проверять соотношение соседних чисел, если a>k*b(k должно быть меньше, чем соотношение толщины), то после толстой линии идёт тонкая, а если a*k<b, то наоборот. Иначе идёт линия такой же толщины. Хотя бы один переход тонкая/толстая линия в коде должен быть, но привязываться что эта линия будет первой не стоит(задача решается и без этого).
Без контрольных линий информации недостаточно. Пусть, к примеру, пришло половина семёрок, половина - девяток. Отнесёшь ли ты их к одному классу или к разным? И ещё - ширина диапазонов классов всегда одинакова или нет?
Ну если ставить задачу так, что мы не знаем даже соотношение толщины линий, тогда нужно строить гистрограмму и смотреть сколько на ней горбов. Если два, значит у нас присутствуют оба класса данных, а если один, значит один из двух, причём мы не сможем сказать какой именно(можно эти комбинации обе выкинуть - не велика потеря). Хотя опять же для гистограммы нужно брать не абсолютные значения толщины, а соотношение толщины соседних линий. Правда если у нас в коде в основном присутствует один класс, то второго горба мы можем просто не заметить, Поэтому желательно дробить код на блоки с фиксированным количеством толстых и тонких линий.
В одной посылке диапазоны для толстой и тонкой лини одинаковы. Диапазоны возникли из-за погрешности. В другой они могут различаться. Если смотреть на глаз. То где 0 а где 1 сразу видно. Но как это описать непонятно((( Самый простой способ это в действительности использовать контрольные лини. Просто я думал, что существует алгоритм классификации.
a9d Диапазоны могут вообще-то пересекаться. Если на начало штрихкода сканер смотрит точно сверху(90 градусов), а конец видит под углом 30 градусов(это конечно весьма утрированный вариант, но читать коды "немного под углом" вполне может понадобиться), то в этом случае линии в конце штрих кода будут ему казаться в два раза тоньше, и если отношение толщины меньше двух, то диапазоны для толстых и тонких линий обязательно пересекутся. Вы бы выложили примеры чисел которые созерцаете, может кто-то уже бы и алгоритм нарисовал.
Не. Угол считывания всегда 90 градусов. Но скорость движения сканера может изменится, по прошествии времени. В одном штрих коде толщина толстой и тонкой одинаковы. Но не факт, что во втором они будут такими же. Забыл сказать. Толстая линия всегда минимум в два раза толще тонкой. Пример: 5 6 12 9 5 6 0 0 1 1 0 0 И все в таком духе. Диапазоны никогда не пересекутся. Ибо между двумя линиями расстояние равно толщине тонкой. Погрешность может достигать 50-60% от толщины тонкой. Блин только, пришло в голову использовать в качестве ориентира расстояние между линиями. Оно ведь всегда равно тонкой.
a9d Попробуй покормить цифирками вот этот код: Код (Text): void decode(unsigned char *res, unsigned char *code, int len) { res[0]=-1; for(int i=1;i<len;i++) if(code[i-1]*181U>code[i]*256U) res[i]=0; else if(code[i-1]*256U<code[i]*181U) res[i]=1; else res[i]=res[i-1]; for(i=0;res[i]==-1;i++); for(int j=0;j<i;j++) res[j]=!res[i]; }
2Black_mirror: Спасибо. Но код иногда сбоит. Последовательность 6,3,7,4,12,11,9. Распознается как 0 1 0 0 1 1 1 А должно быть 0 0 0 0 1 1 1. На тройке слетает.
a9d Это мой алгоритм пересказанный вашими словами сбоит, а мой должен выдавать 1010111, потому что 3 и 4 почти в два раза меньше чем 6 и 7, а границу я выбрал в 1.414. Си под рукой нету, вот аналог на асме: Код (Text): include '%fasminc%\win32ax.inc' .data s1 db 6,3,7,4,12,11,9,0 s2 db '9' .code start: mov esi,s1 mov edi,s2 .next: inc esi inc edi cmp byte [esi],0 jz .exit mov al,181 mul byte [esi-1] mov al,'0' cmp ah,[esi] jae .save mov al,181 mul byte [esi] mov al,'1' cmp [esi-1],ah jbe .save mov al,[edi-1] .save: mov [edi],al jmp .next .exit: mov esi,s2 .for2: inc esi cmp byte [esi],'9' jz .for2 mov al,[esi] xor al,1 .for3: dec esi mov [esi],al cmp esi,s2 jnz .for3 invoke MessageBox,0,s2,"0",0 invoke ExitProcess,0 .end start
В теории все гладко было. На практике выползли косяки. Задача была решена вводом контрольных линий. Получилось не так красиво но пашет)) Но все равно спасибо.