Перейти к содержимому
Compvision.ru

Smorodov

Главные администраторы
  • Количество публикаций

    3 873
  • Зарегистрирован

  • Посещение

  • Days Won

    346

Сообщения, опубликованные пользователем Smorodov


  1. Есть ли какие-то методы, которые могут сносно классифицировать рукописные символы? (буквы, цифры)

    Вариант - нейросеткой. Но.. может тут OpenCV лучше справится? :)

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

    Не знаю поможет ли, но вот материальчик по распознаванию человека по подписи: SignRecognition_engl_.pdf

    Еще статейка (распознавание рукописных формул): http://stephane.lavirotte.com/research/bib...ll-etal1999.pdf

    Генетический алгоритм распознавания рукописных чисел: http://www.ppgia.pucpr.br/~soares/download/sibgrapi01-ga.pdf

    Еще пара подходов: http://w3.gel.ulaval.ca/~mbusque/reports/artmap_digit.pdf


  2. Изучаю тут код приведённый выше, есть несколько вопросов. Если не сложно - ответьте пожалуйста! :)

    А зачем он там вообще появляется? :) Просто интересно..

    Вот здесь не понял, зачем нам нужно сделать аппроксимацию контуров полигонами?

    Чувствую, что здесь ключевой момент, а он у меня остался за гранью понимания. Мы же сходство контуров определяем не по числу, представленному площадью фигуры.. Мало ли одинаковых площадей у разных фигур.. :)

    Что за читалка точек такая? Это массив хранящий все наши контурные точки, при необходимости к которым можно доступиться?

    Я, кстати, никак не могу найти официальное руководство к OpenCV. Это бы много вопросов решило.. Не подскажите где оно есть?

    Белый бордюр не знаю зачем, это у Интел надо спрашивать, долго мучился с этим, не мог понять, почему моменты неправильно ищет.

    Контуры в OpenCV задаются цепями Фримана (это последовательность команд такая вверх, вверх-влево, влево,... и т.д.), работать с этим не удобно.

    Аппроксимация нужна чтобы получить координаты границы контура в виде последовательности точек p(x,y), которые можно потом линией соединить, и получится граница контура (полигон). параметры функции аппроксиматора задают с какой погрешностью допустимо это сделать.

    CvSeq - аналог класса Vector в c++

    CvSeqReader - это что то похожее на итераторы класса Vector в c++

    Офиц. руководство


  3. Это Вы имеете ввиду оценку по схожести контуров?

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

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


  4. Ааа.. вон оно в чём смысл!! Понятно. Спасибо большое за художество! :)

    Таким образом, в принципе, можно ведь и жесты пальцев распознавать?

    А к изменению масштаба как оно относится?

    А не влияет масштаб :)

    Поправил картинку выше.


  5. Smorodov

    По поводу картинки.. Насколько я понимаю, те подписанные числа, это и есть степени схожести контуров?

    Т.е. классифицировать один от другого можно по некоторому пороговому числу..

    А к поворотам это решение случаем не чувствительно? Ну мало ли конечно, контур как контур, какая разница в какую сторону развёрнут предмет.. :)

    Интересно вот.. а числа и символы таким алгоритмом тоже можно распознавать по порогу? :)

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

    PS постараюсь раздобыть и установить C-Builder, чтобы запустить этот проект. Винда где-то тоже валялась на дисках.. :)

    Картинка с другого моего сайта (старого)

    (думаю с цифрами получится)

    Повороты не имеют значения. Правда и 6 от 9 тоже не отличить :)

    CompVi4.jpg

    Цифры означают степень различия, насколько я помню. Красятся в красный или зеленый по порогу (у красного человечика пропорции другие, а зеленые - клоны повернутые).


  6. О блин, а вот этого я совершенно не заметил! :)

    Тогда, конечно, ясное дело, что разница тут огромная!

    А с поворотом как быть? Самому уже как-то определять угол поворота и разворачить? Затем масштабировать, а уж после этого подсовывать распознавательным методам..

    Ну, если руки не выворачивать, то я думаю и без разворота можно обойтись :)

    А если выворачивать, то вписывать в эллипс и разворачивать ориентируясь на большую ось (на самом деле на ось инерции фигуры). Или использовать момент товарища Ху ему без разницы угол и масштаб, ему форма важна.


  7. Спасибо за информацию!

    По поводу видео.. А что в нём особенного? Когда я его смотрел раньше - сразу в голову пришло просто решение:

    1. Фоткает фон без руки

    2. Снимает руку камерой

    3. Выделяет разницу => остаётся одна (например) белая рука на чёрном фоне. Выделить контуром - просто отступить на некоторое расстояния в стороны :)

    С определением клика сложнее конечно. Ну тут я ничего придумать не могу.. кроме как определения длины нужного пальца в процентном соотношении :)

    Кстати, а для подобных штук обычные веб-камеры подходят? Или они какие-то высокого разрешения используют?

    Хочу предупредить, что методы PCA и HMM чувствительны к повороту и к тому же выловленную картинку придется масштабировать в некий стандартный размер.

    Я еще про моменты Ху :) ( Hu moments ) забыл, они не имеют зависимости от масштаба и поворота, а характеризуют именно форму контура.

    В офиц. руководстве (от Интел) это есть.

    Для таких вещей как анализ контура во втором случае идеально подходит. На форуме еще примеры по контурам были. (Определение похожести контуров).

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

    В тех роликах, я думаю, применяется разрешение 640х480, таких камер уже достаточно много. И скорость работы приемлемая. У меня такая на Asus EEE установлена, OpenCv притормаживает, но в целом сносно работает.

    ЗЫ: Там (в ролике) фон динамический, есть разница :)


  8. Хочу попытаться сделать что-то типа такого:

    но опыта очень и очень мало в распознавании образов, а в программировании, обратно - достаточно :) Только на одном опыте программинга далеко в этом деле не уедешь.

    Можете что-то порекомендовать? В какую сторону хотя бы смотреть? На какие алгоритмы стоит обратить внимание?

    Что то это очень очень напоминает метод главных компонент :) или, в простонародье, principal component analysis (PCA)

    Пример здесь

    Хотя скрытые марковские модели (по английски HMM (для google)) наверное надежнее будут.

    Пример здесь

    Мне еще вот это нравится:

    а это уже деформируемые модели, родственные жадным змеям, но только сложнее малость.


  9. А каков при этом сам алгоритм поиска точки?

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

    См. начиная со стр.12 этого документа: CV_Руководство.pdf


  10. А зачем требуется такая калибровка? Почему не достаточно 4х крайних точек?

    Вот здесь тоже кучей точек калибруют

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

    Калибровка исправляет сложные искажения, которые определяются неидеальностью формы линзы, ошибками её механической фиксации, ошибки изготовления сенсора.

    Когда все это складывается получается достаточно сложная форма искажений, как в кривом зеркале, которую зная лишь 4 точки исправить не удастся. Т.к. одна кривизна посередине, а по краям уже совсем другая.

    Вот тут пояснения (лекции МГУ): Модель и калибровка камеры


  11. Открыл несколько исходников приложенных здесь - народ программирует в Borland C Builder..

    А неужели никто из Вас не пытался программировать и под Линукс? Под другие ОСИ? Пытаться использовать кроссплатформенное программирование? Почему Вы так привязаны к винде?

    Спрашиваю не с наездом, ни в коем случае! Просто интересно. :(

    Да и в целом, насколько OpenCV готова для кроссплатформенного кода? Я только начинаю заниматься компьютерным зрением и меня интересует именно кроссплатформенный код.. (хотя бы между windown & linux).

    Большой разницы нет, OpenCV одинаково работает и на винде и на линуксах, просто примеры приведены для билдера, т.к. у меня сейчас билдер, а код то один и тот же что для линукса, что для винды. Может с выводом в форму поколдовать придется, но такой вывод далеко не всем нужен.

    Для линукса есть преимущество по моему IPP для него распространяются бесплатно.

    Да и на микроконтроллерах лучше линукс (хотя тоже не всегда).

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

    ЗЫ: cfr, насколько я знаю работает под линуксом, и очень доволен. Можете с ним связаться.


  12. А как создаются классификаторы? и для рук и ног существуют класификаторы?)

    Для OpenCV я сделал перевод их руководства, он лежит здесь: Обучение классификаторов Хаара

    Насчет рук и ног, в примере FaceDetect, в директории с классификаторами лежат каскады для нижней части тела haarcascade_lowerbody и для верхней части тела haarcascade_upperbody, а также для человека в полный рост haarcascade_fullbody.


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

    Однако алгоритм работает очень неплохо.

    hmm.jpg

    Архив с проектом: HMM.RAR

    • Like 1

  14. Корректно выводит изображения ширины не кратной 8 и изображения с типом элемента не IPL_DEPTH_8U.

    Думаю что должен выводить любые изображения.

    #define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4)
    //---------------------------------------------------------------------------
    // Создание API шного битмапа из интеловского RGB изображения
    //---------------------------------------------------------------------------
    HBITMAP CreateRGBBitmap(IplImage* _Grab)
    {
    char *App;

    IplImage *_Grab3=0,*_Grabf=0;

    LPBITMAPINFO lpbi = new BITMAPINFO;
    lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    lpbi->bmiHeader.biWidth = _Grab->width;
    lpbi->bmiHeader.biHeight =_Grab->height;
    lpbi->bmiHeader.biPlanes = 1;
    lpbi->bmiHeader.biBitCount = 24;
    lpbi->bmiHeader.biCompression = BI_RGB;
    lpbi->bmiHeader.biSizeImage = WIDTHBYTES((DWORD)_Grab->width * 8) * _Grab->height;
    lpbi->bmiHeader.biXPelsPerMeter = 0;
    lpbi->bmiHeader.biYPelsPerMeter = 0;
    lpbi->bmiHeader.biClrUsed = 0;
    lpbi->bmiHeader.biClrImportant = 0;
    void* pBits;
    HBITMAP hBitmap = CreateDIBSection(
    NULL,
    lpbi,
    DIB_RGB_COLORS,
    (void **)&pBits,
    NULL,
    0 );
    delete lpbi;
    if ( hBitmap )
    App=(char*)pBits;
    // Если глубина изображения не IPL_DEPTH_8U (однобайтовое целое), конвертируем
    if(_Grab->depth!=IPL_DEPTH_8U)
    {
    _Grabf=cvCloneImage(_Grab);
    if(_Grab) {cvReleaseImage( &_Grab);}
    _Grab = cvCreateImage( cvSize(_Grabf->width,_Grabf->height),IPL_DEPTH_8U,_Grabf->nChannels);
    cvConvert(_Grabf,_Grab);
    if(_Grabf) {cvReleaseImage( &_Grabf);}
    }
    // Если изображение содержит один канал, создаем трехканальное изображение
    // Серое или бинарное
    if(_Grab->nChannels==1)
    {
    _Grab3 = cvCreateImage( cvSize(_Grab->width,_Grab->height),IPL_DEPTH_8U,3);
    cvMerge(_Grab,_Grab,_Grab,NULL,_Grab3);
    }
    // Если входное изображение трехканальное, просто копируем указатель на него
    // Цветное
    if(_Grab->nChannels==3)
    {
    _Grab3=_Grab;
    }
    // Получаем указатель на данные
    unsigned char* data;
    cvGetRawData(_Grab3, (uchar**)&data);
    // Копируем данные
    if(_Grab3)
    {
    for (int i=0;i<_Grab->height;i++)
    {
    memcpy(App+_Grab3->widthStep*(_Grab3->height-i-1),data+_Grab3->widthStep*i,_Grab3->width*3);
    }
    }
    // Очищаем память если создавали изображение, а не копировали указатель
    if(_Grab->nChannels==1) {cvReleaseImage( &_Grab3);}

    return hBitmap;
    }
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    // Функция вывода изображения на HANDLE оконного компонента
    //---------------------------------------------------------------------------
    void APIDrawIpl(int x,int y,IplImage* _Grab,void *HANDLE)
    {
    HDC hMemDC,hDC;
    hDC=GetDC(HANDLE);
    hMemDC = CreateCompatibleDC(hDC);
    HBITMAP Bitmap=CreateRGBBitmap(_Grab);
    SelectObject(hMemDC,Bitmap);
    BitBlt(hDC,x,y,_Grab->width,_Grab->height,hMemDC,0,0,SRCCOPY);
    DeleteObject(Bitmap);
    DeleteDC(hMemDC);
    DeleteDC(hDC);
    }
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------[/code]


  15. Большое спасибо!Разобрался)

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

    CString fname;  //Переменная для хранения имени файла
    CFile file; //обьект класса CFile

    CFileDialog dlgOpen(TRUE, L"txt",L"",
    OFN_HIDEREADONLY, L" JPEG(*.JPG;*.JPEG;*.JPE)| *.jpg|BMP(*.BMP;*.RLE;*.DIB)| *.bmp| PNG(*.PNG)|*.png| TIFF(*.TIF;*.TIFF)|*.tif| ALL
    Formats(*.*)|*.*|", this);

    if(dlgOpen.DoModal()==IDOK)
    {
    fname = dlgOpen.GetPathName();
    }
    else
    return;

    char* FailDir = fname; //Проблемная строка[/code]

    Выдает ошибку: cannot convert from 'CString' to 'char *'

    Мало того даже если убрать проблемную строчку и написать char* FailDir = "Имя файла.жпег"; и вызвать, заранее написанную функцию, вывода изображения средствами OpenCV, выводится почему-то пустое серое окно.... А если не вызывать до этого окно поиска файла то все отображается отлично... Вот такие вот странности)

    Мне кажется, проблема в том, что при вызове окна fname = dlgOpen.GetPathName(); заносит в fname строку типа w_char (два байта на символ), а не char, может нужно просто преобразовать в char? Я не спец по MFC, но вроде там есть функция, типа OEMToChar, или что то в этом роде.

    Посмотрел. Есть функция wctomb(char,t_wchar)

×