Задача класификации данных. Нуже алгоритм.

Тема в разделе "WASM.A&O", создана пользователем a9d, 4 май 2010.

  1. a9d

    a9d New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2006
    Сообщения:
    234
    Адрес:
    Zimbabwe
    Бьюсь об стенку над одной задачей. Задача связанна с микроконтроллерами. Поэтому ресурсы ограничены.

    На входе небольшая посылка данных. Данные это набор чисел от 0 до 255.
    Нужно их отнести к тому или иному классу данных. Т.е. к 0 или 1. И уже на основе полученного кода сделать определенные действия.

    Пример:

    между 5-7 это 0
    между 9-11 это 1

    Но тут появилась одна большая проблема.
    В первой посылке класс А может занимать диапазон от 5-7 а уже во второй 9-11. При четком указывании диапазонов данные воспринимаются не правильно.
    Но всегда известно, что класс А всегда меньше класса Б. Между ними всегда есть небольшой промежуток.
    В посылка всегда будет присутствовать хотя бы один класс данных.

    ЗЫ: Проще говоря нужно обработать штрих код. Но в этом случае просто неизвестна заранее толщина линий.
     
  2. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    В штрихкодах толстые и тонкие линии обычно образуют группы с одинаковым количеством толстых и тонких линий(например 5 тонких и 3 толстые). То есть можно просто найти среднюю толщину линий и использовать это число в качестве границы. Еще можно получив первое число установить две контрольные точки, одну к примеру на 40%(зависит от соотношения толщины линий) больше полученного числа, а вторую меньше. И пока числа не выйдут за этот диапазон, считаем что они принадлежат к одному классу(можно даже обновлять точки по последнему полученному числу), а как только получим число за пределеми этого диапазона, то сможем однозначно определить где проходит граница.
     
  3. a9d

    a9d New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2006
    Сообщения:
    234
    Адрес:
    Zimbabwe
    Да, походу придется использовать в начале кода контрольную линию. Например первая всегда толстая и относительно нее дальше ориентироваться. Хотя это не особо мне нравиться.

    Капец. Смотря на числа определяю точно где 0 а где 1. Но даже не представляю как это описать.
     
  4. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    a9d
    Еще можно проверять соотношение соседних чисел, если a>k*b(k должно быть меньше, чем соотношение толщины), то после толстой линии идёт тонкая, а если a*k<b, то наоборот. Иначе идёт линия такой же толщины. Хотя бы один переход тонкая/толстая линия в коде должен быть, но привязываться что эта линия будет первой не стоит(задача решается и без этого).
     
  5. Ravager

    Ravager New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2008
    Сообщения:
    34
    Без контрольных линий информации недостаточно. Пусть, к примеру, пришло половина семёрок, половина - девяток. Отнесёшь ли ты их к одному классу или к разным? И ещё - ширина диапазонов классов всегда одинакова или нет?
     
  6. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    Ну если ставить задачу так, что мы не знаем даже соотношение толщины линий, тогда нужно строить гистрограмму и смотреть сколько на ней горбов. Если два, значит у нас присутствуют оба класса данных, а если один, значит один из двух, причём мы не сможем сказать какой именно(можно эти комбинации обе выкинуть - не велика потеря). Хотя опять же для гистограммы нужно брать не абсолютные значения толщины, а соотношение толщины соседних линий. Правда если у нас в коде в основном присутствует один класс, то второго горба мы можем просто не заметить, Поэтому желательно дробить код на блоки с фиксированным количеством толстых и тонких линий.
     
  7. a9d

    a9d New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2006
    Сообщения:
    234
    Адрес:
    Zimbabwe
    В одной посылке диапазоны для толстой и тонкой лини одинаковы. Диапазоны возникли из-за погрешности.
    В другой они могут различаться.

    Если смотреть на глаз. То где 0 а где 1 сразу видно. Но как это описать непонятно(((

    Самый простой способ это в действительности использовать контрольные лини. Просто я думал, что существует алгоритм классификации.
     
  8. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    a9d
    Диапазоны могут вообще-то пересекаться. Если на начало штрихкода сканер смотрит точно сверху(90 градусов), а конец видит под углом 30 градусов(это конечно весьма утрированный вариант, но читать коды "немного под углом" вполне может понадобиться), то в этом случае линии в конце штрих кода будут ему казаться в два раза тоньше, и если отношение толщины меньше двух, то диапазоны для толстых и тонких линий обязательно пересекутся.
    Вы бы выложили примеры чисел которые созерцаете, может кто-то уже бы и алгоритм нарисовал.
     
  9. a9d

    a9d New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2006
    Сообщения:
    234
    Адрес:
    Zimbabwe
    Не. Угол считывания всегда 90 градусов.
    Но скорость движения сканера может изменится, по прошествии времени.
    В одном штрих коде толщина толстой и тонкой одинаковы. Но не факт, что во втором они будут такими же.
    Забыл сказать. Толстая линия всегда минимум в два раза толще тонкой.

    Пример:
    5 6 12 9 5 6
    0 0 1 1 0 0

    И все в таком духе.
    Диапазоны никогда не пересекутся. Ибо между двумя линиями расстояние равно толщине тонкой.
    Погрешность может достигать 50-60% от толщины тонкой.

    Блин только, пришло в голову использовать в качестве ориентира расстояние между линиями. Оно ведь всегда равно тонкой.
     
  10. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    a9d
    Попробуй покормить цифирками вот этот код:
    Код (Text):
    1. void decode(unsigned char *res, unsigned char *code, int len)
    2. {
    3.     res[0]=-1;
    4.     for(int i=1;i<len;i++)
    5.         if(code[i-1]*181U>code[i]*256U)
    6.             res[i]=0;
    7.         else if(code[i-1]*256U<code[i]*181U)
    8.             res[i]=1;
    9.         else
    10.             res[i]=res[i-1];
    11.     for(i=0;res[i]==-1;i++);
    12.     for(int j=0;j<i;j++)
    13.         res[j]=!res[i];
    14. }
     
  11. a9d

    a9d New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2006
    Сообщения:
    234
    Адрес:
    Zimbabwe
    2Black_mirror: Спасибо. Но код иногда сбоит.
    Последовательность 6,3,7,4,12,11,9. Распознается как 0 1 0 0 1 1 1
    А должно быть 0 0 0 0 1 1 1.
    На тройке слетает.
     
  12. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    a9d
    Это мой алгоритм пересказанный вашими словами сбоит, а мой должен выдавать 1010111, потому что 3 и 4 почти в два раза меньше чем 6 и 7, а границу я выбрал в 1.414. Си под рукой нету, вот аналог на асме:
    Код (Text):
    1. include '%fasminc%\win32ax.inc'
    2.  
    3. .data
    4.  
    5. s1 db 6,3,7,4,12,11,9,0
    6. s2 db '9'
    7.  
    8. .code
    9.  
    10. start:
    11.         mov esi,s1
    12.         mov edi,s2
    13. .next:
    14.         inc esi
    15.         inc edi
    16.         cmp byte [esi],0
    17.         jz .exit
    18.         mov al,181
    19.         mul byte [esi-1]
    20.         mov al,'0'
    21.         cmp ah,[esi]
    22.         jae .save
    23.         mov al,181
    24.         mul byte [esi]
    25.         mov al,'1'
    26.         cmp [esi-1],ah
    27.         jbe .save
    28.         mov al,[edi-1]
    29. .save:
    30.         mov [edi],al
    31.         jmp .next
    32. .exit:
    33.         mov esi,s2
    34. .for2:
    35.         inc esi
    36.         cmp byte [esi],'9'
    37.         jz .for2
    38.         mov al,[esi]
    39.         xor al,1
    40. .for3:
    41.         dec esi
    42.         mov [esi],al
    43.         cmp esi,s2
    44.         jnz .for3
    45.         invoke MessageBox,0,s2,"0",0
    46.         invoke ExitProcess,0
    47.  
    48. .end start
     
  13. a9d

    a9d New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2006
    Сообщения:
    234
    Адрес:
    Zimbabwe
    В теории все гладко было. На практике выползли косяки.
    Задача была решена вводом контрольных линий. Получилось не так красиво но пашет))

    Но все равно спасибо.