Автор Тема: OpenCV / обучаване на Haar cascade класификатори  (Прочетена 50289 пъти)

go_fire

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 8780
  • Distribution: Дебиан Сид
  • Window Manager: ROX-Desktop / е17
  • кашик с гранатомет в танково поделение
    • Профил
    • WWW
Я осъзнавате ли, че това е първият път, в който Гейта публикува своя снимка???
Активен

В $por4e2 e истината  ;)

***

Aко даваха стипендия за най-глупави, щях да съм човека с най-много Mини Kупъри

***

Reborn since 1998 || 15.09.2007 totally М$ free && conscience clear

4096bits

  • Напреднали
  • *****
  • Публикации: 6152
    • Профил
Надвил е страха си  :D
Аз още не мога
Активен

As they say in Mexico, "Dasvidaniya!" Down there, that's two vidaniyas.

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Хм, на път съм да разбера как работи още една антиутопична играчка....

http://postimg.org/image/vc6nj2t5j/

http://postimg.org/image/9uyp884t9/


Оказва се че това наистина го има и си работело съвсем прилично (с точност над 95% в някои реализации).

Оказва се също че е просто (е не изцяло, класифицирането на буквите е голяма играчка, трябва да се изнамерят достатъчно изображения с всички възможни букви и да се тренират модели) - та заради това за целта използвам tesseract за последната част. Което включва викането на външна команда и този подход изключва работата с видео в реално време - хардуерът няма да се справи.

В общия случай има няколко стъпки:

1) Локализация. Това е стъпката на която откриваме потенциални регистрационни номера в сцената. Аз го направих просто и заради това дава малко повече false positives от оптималното, но пък не е и голям проблем. False negatives почти никога не дава. Номерът е прост - blur-ваме леко картинката, за да избегнем "шум" от сорта на дребни петна, отблясъци и т.н., прилагаме gaussian threshold върху картинката, вадим контурите и търсим контур, който 1) е достатъчно голям, контури от десетина пиксела примерно не ни трябват и 2) bounding rect-а му отговаря на определени геометрични критерии. Критериите са отношението между ширина и височина, а въпросното го намерих в интернет, оказва се че е стандартизирано, поне за регистрационните табели в ЕС.

Малко изхитряване е да "изхвърляме" потенциалните кандидати, които "включват" други такива в себе си - това намаля обикновено с 1-2 бройки false позитивите (като се има предвид че на сцена обикновено има до десетина такива, това пак е приемлива сметка).


2) Препроцесинг. За всеки такъв регион обръщаме изображението в grayscale и правим още един път thresholding. Целта е да се "откроят" тъмните петна (буквите) от светлите петна (фона на регистрационния номер). Това само по себе си не ни върши идеална работа, защото разни винтчета, гайки, логото на европейския съюз с надписа "BG", както и обикновено една черна рамка около регистрационния номер, остават. Остава и "случаен" шум - сенки, кал по номера, отблясъци и т.н. Последният се отстранява с морфологични операции - dilate/erode.

3) Сегментация. Ако резултата от стъпка 2) я подадем на tesseract, то той обикновено се задавя много лошо - заради рамката на номера, логото встрани, въпросните нитове и винтове за които е набиван знака и т.н. За да изчистим тези неща, отиваме по-нататък - от регистрационния номер "изваждаме" всяка буква или цифра. За целта threshold-ваме изображението отново и вадим контурите. Прекалено малките контури ги изхвърляме (така си заминават болтчетата и случайно каквито дребни петна са останали) и отново налагаме геометричен филтър, възползвайки се от факта, че се ползва един и същ шрифт и отношението височина/ширина е в някакви рамки. Отношението височина на буквата/височина на табелата също е hint, но не го ползвам. Така вадим една по една всички букви - можем съответно и да направим още една проверка дали това е регистрационен номер - ако има по-малко от 6 букви, значи не е и не го подаваме нататък

4) Разпознаване. В случая с tesseract, "лепя" отново всичките букви/цифри на бял фон и му ги подавам, но може и буква по буква. Тъпото е че въпросната сегментация от горния параграф, tesseract-а пак ще я направи, та може би да му се подава буква по буква ще е по-добре.


tesseract-а нямаше нужда да се "обучава" за шрифта дето се използва в табелите, справя се и така много добре.


Значи остава някой ден да имам време и да видя как стои въпроса с тренирането на модели и кое върши работа най-добре там, големите глави със сигурност са го измислили. Това ще позволи да стане в реално време върху видео.

Сега няма как да се похвали с велики качества и >95% акуратност, но и така работи довоооолно добре.
Активен

"Knowledge is power" - France is Bacon

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Мммммм тва с разпознаването на регистрационни табели във видео не е толкова лесна работа, доста оптимистично съм гледал на нещата :)

Първо, изчетох отгоре-отгоре няколко paper-а за да видя големите глави как подхождат към проблема с разпознаването на символи. Явно масово прилаганото решение е трениране на SVM класификатор (статистически метод, не съм разбрал още достатъчно добре как работи, но на първо четене странно напомня на марковските вериги дето ги ползвах в hashkill-а за да генерирам пароли по модел, трениран от речник ).

SVM модела се тренира с HOG хистограми. Доколкото се опитах да разбера що е то HOG, не мога въобще да разбера защо това нещо работи. В бедните ми представи за нещата, би трябвало да имаме ужасно много false позитиви от съвсем различно изглеждащи обекти (или обратно, негативи от ужасно сходни). Та това е нещо, което трябва да се опитам да разбера като хората.

В OpenCV няма готова функция, която да смята въпросните HOG хистограми, та срам не срам преправях чужд код.

Извън това че още не мога да осмисля теорията зад тези две явления като хората (което е огромен проблем и така става с тъпи и нетърпеливи хора), все пак успях да нахвърлям някаква груба основа за нещата - тренирам SVM модела (отвратителна работа, много ръчен труд, свързан с рязане и оразмеряване на картинки, който засега не съм автоматизирал като хората).

Входните данни за модела (за български регистрационни номера) ми е следния (след сума ти къртовски труд):

http://postimg.org/image/62iykuxf3/

За всеки възможен символ имаме три изображения, върху които смятаме въпросните хистограми на ориентирани градиенти. Това е ужасно малко и големите глави твърдят че ще ми трябват поне едно стотина като за начало ако искам прилична акуратност. Е заклевам се, успея ли някога да го постигна това, НЯМА да го споделям безплатно - тъпия скучен упорит труд си заслужава заплащане - и както човек може да се досети, готови модели няма (изключай усилията на един пич да направи същото за испанските регистрационни табели, където отсъстват няколко букви).


Както и да е, с този беден модел, резултатът е следния:

http://postimg.org/image/ea6a2uuxb/

И има ужасно много проблеми.

Първият очевиден проблем идва от кофти модела - символите А, 8 и Т се разпознават като "0". Всъщност, на някои кадри, 8 успешно се разпознава, но A и T - никога.

Вторият проблем - сегментацията ми не е перфектна и трябва да я подобря. Понякога влизат грешни контури и съсипват всичко, въпреки всичките тези малоумни проверки. Не е критично, но съсипва доволно кадри, в които иначе бихме имали шанс да познаем номера. Проблемът тук е крив, защото осъзнах какъв е проблема (идиотския алгоритъм след морфологичните операции започва да вярва че разстоянието между буквите всъщност е затворен контур) - за което лесни евристични проверки няма, понеже въпросния контур твърде много напомня на варианта с "о" или нула - макар и разкривена. Трябва някакъв по-интелигентен механизъм за тва. Единствения "тъп" критерии, който ми хрумва е rounding rect-овете на отделните букви да не се презастъпват и за тези където има презастъпване да не правим сметки, това може би ще сработи, но ще срине още производителността.

Третият проблем - производителността, сега 25fps видео се срива до около 2-3 fps в следствие на всички тези сметки. Но видеото е 720p в крайна сметка, а доста неща има за оптимизиране, така че това не ми е проблема. Бавенето не идва от SVM разпознаването, идва от сегментацията, която при мен е доста....деазнам, малко като руския цар подхождам към проблема. Има голям мегдан за подобрение.


Като цяло се нервирам, ще се окаже все пак играчка това.
« Последна редакция: May 28, 2015, 00:43 от gat3way »
Активен

"Knowledge is power" - France is Bacon

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
А, то не било чак толкова сложно....всичко опирало до съставянето на по-качествен модел.

http://postimg.org/image/d447wckof/full/

Разпознава относително коректно вече....е тук-таме в някой кадър "3" става "9", "8" става "0". a "C" в един момент прилича на "0", но напредъкът е голям.


Всъщност оказва се че при така зададените параметри с които се тренира (36 символа общо, 20x20 резолюция на картинка, 4 HOG хистограми, общо 64 bin-а) имаме много бързо "насищане" на акуратността при добавяне на нови картинки към training set-а. До около 5 картинки на символ, акуратността скача рязко, след това нормално файдата започва рязко да спада. При 10 картинки на символ с които тренираме модела, тестовете срещу нов set от картинки (A-Z, 0-9) показва 92% акратност в разпознаването - което означава че само с 3 от 36-те нови символа не са разпознати коректно.

Лошото е че и да тествам с 20 картинки на символ да тренирам модела, трудно ще скочи акуратността с повече от 1-2 процента и не знам доколко си оправдава усилията.

Това са тестове срещу "културни" картинки - демек почти същия шрифт, символите не са наклонени и т.н. Съответно срещу сегментираните символи от сцената, нямаме такъв успех както се вижда (коректно разпознатия номер е в около 50% от сцените, в останалите обикновено имаме 1 символ грешка, много рядко 2 символа). Това е далеч от 92-та процента при теста с "културния" вход. Откъдето стигам до извода, че сегментацията и локализацията ми е все още доста некадърна.

Специално локализацията използва адаптивен thresholding, което е хубаво защото работи относително добре при всякаква осветеност на сцената. Но не се справя добре с хвърлени сенки и дребен "шум" по сцената. Навсякъде из paper-ите хвалят OTSU thresholding-а и пробвах с него - обаче тук има друг проблем - параметрите му трябва да се настройват ръчно за всяко различно видео, защото един threshold работи много добре за едно видео и много зле за друго. Автоматично няма как да го подбираме, трябва някакъв изкуствен интелект да ги взема такива решения.

Поради което ще се чете още, не може да няма по-добър подход. В крайна сметка може би има по-добър подход от thresholding-а като цяло.
Активен

"Knowledge is power" - France is Bacon

4096bits

  • Напреднали
  • *****
  • Публикации: 6152
    • Профил
Достатъчно бързо ли е пайтънчето за тези неща?!
Активен

As they say in Mexico, "Dasvidaniya!" Down there, that's two vidaniyas.

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Това няма голямо значение, защото "тежката" работа я върши opencv, която е c++ библиотека. В случаите в които няма наготово opencv функция или набор от такива, за да се свърши нещо и се налага сам да ръчкаш по изображенията (които са numpy матрици "по начало") тогава може да се появят проблеми с производителността.

python е далеч по-удобен език за експерименти от друга страна, спестява ти доста съмнителни радости.
Активен

"Knowledge is power" - France is Bacon

4096bits

  • Напреднали
  • *****
  • Публикации: 6152
    • Профил
Имаш ли някакви урочета за тоя език. Аз съм насвалял разни, ама там синтаксис не ме грее толкова или пък how to това и онова. Интересува ме по-скоро да си направя някои нещица за линукса, че има опции на някои от командите трудно ги помня. Там взаимодействие със системата.
Активен

As they say in Mexico, "Dasvidaniya!" Down there, that's two vidaniyas.

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Нямам идея, аз не съм много по нещата с уроците.

Python ужасно много време го ненавиждах като език и го приемах като някаква модернизирана версия на Perl. Синтаксисът специално ме вбесяваше (и още ме вбесява на моменти). Обаче трябва да си призная че върши идеална работа за много неща и спестява ужасно много глупости. Що се отнася до performance-а, никой не пречи да си напишеш критичния код на C, да го билднеш под формата на shared библиотека и със swig да го ползваш от python. Доста досаден и противен момент са типовете данни в случая, но какво да се прави.


P.S тренирах модел с повече картинки на символ - 20, както и оптимизирах доста алгоритъма така че вече кажи-речи става в реално време без голямо дропене на фреймрейта на изходното видео. Добавих и подръжка на гадните квадратни регистрационни номера (ЕГАТИ УЖАСА е това - номера е подреден на два реда и ти имаш сегментирани региони с координати, широчина и височина по екрана - честито разпознаване кои са буквите от горния ред и кои са буквите от долния ред предвид възможността да го гледаш това под ъгъл). Значително подобрих препроцесинга и локализацията - вече не използваме адаптивен thresholding (ужасно бавен е), вместо това използвам комбинация от median филтър, за да отсявам дребни артефакти плюс canny edge, за да хващам рамката на регистрационния номер.

Та всичко това доведе до повишено бързодействие и акуратност:

http://postimg.org/image/3to58oz2v/

Обаче има отново доста проблемни моменти. При квадратните номера, символите са по-дребни и по-наблъскани, сегментацията не е перфектна и като резултат ето този голем черен джиБ:

http://postimg.org/image/4l1n3dygv/

..не може да се похвали с нито едно успешно разпознаване. В случаят имаме огромен проблем с цифрата "6".

Забавното е че като investigate-нах проблема, оказва се че шрифта за регистрационните номера в Европа е стандартизиран по DIN-1451 или нещо от сорта, но има вариации по отношение на това. В източна европа, 6 и 9 не се изписват с голямата завъртулка (вж скрийншота), докато в западна Европа се изписва. Като резултат от това, сега моделът ми има training изображения предимно от западноевропейския шрифт и българските номера го отнасят лошо. И както се вижда, шестицата се разпознава като осмица или девятка. Единственото решение на проблема е тренирането на още по-свински модел, където присъстват двата варианта....или алтернативно трениране на един модел за нашите номера и друг модел за европейските.

Та извода е, още по-брутално трябва да се тренира модела. А за жалост training samples вече трудно откривам :(


P.S за да илюстрирам по-добре проблема, това е български номер:



Това е португалски:




6 и 9 много много не си приличат....и съответно тормозят OCR-ването...


Това не е единственото недобре стандартизирано нещо в тази област де, другото е нулите. В някои държави няма никаква разлика между 0 и O, защото или нямат буквата О в номерата си, или нямат цифрата нула в номерата си, или са разделени като при нас на части само с букви и само с цифри. При повечето въпреки всичко имаме малка разлика между О и нула в шрифта, което помага на моето OCR-ване, но това е ambiguous. Сега за да е още по-забавно, немците дебело си подчертават нулата като нула, толкова дебело че започва да прилича на съвсем различен символ и се опасявам че ако вкарам няколко семпъла в trainset-а от немски шрифтове, ще настане същата боза като с 6-цата и 9-ката. Очевидно за да имаш високоакуратна система за разпознаване на табели, трябва да си го тренираш срещу изображения на номера от държавата. Това че сме в ЕС и има някакво стандартизиране - очевидно последното касае само размера на табелите и онази синята част там с логото на ЕС и кода на държавата...
« Последна редакция: May 30, 2015, 18:13 от gat3way »
Активен

"Knowledge is power" - France is Bacon

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Мех, готово, разпознаваме вече български регистрационни номера на видео с доста висока акуратност (трудно ми е да дам точни цифри, но е над 90%, вероятно над 95%, но в идеалния случай, в естествена среда може да се случи номерата да ти идват под достатъчно кофти ъгъл или с достатъчно крива сянка - за второто, с IR камера и нещо дето светка, на практика си докарваме идеални условия).


Работи напълно в реално време, както може да се види на видеото (с камера срещу браузъра):

https://www.youtube.com/watch?v=br6kPmdU3us

Има случайни грешки, които могат да се "изчистят" доста лесно - ако се имплементира прост алгоритъм от сорта на "ако си видял N кадъра в които този номер се е срещал, тогава го обяви за открит" - това избягва моментите с бързите движения и кофтите ъгли на камерата, които временно дават "калпав" резултат. За N може да имаме ниска стойност, примерно дори 2-3 върши работа, за да отсява "шума".


Това е на базата на доста подобрен статистически модел за разпознаване, доста оптимизиран localization алгоритъм и въведени правила, които са валидни само за български номера (някъде във видеото много добре си личи как fail-ваме срещу някакъв чешки номер, който прилича на български и Z го разпознава като 2 - защото съм изключил "неизползваните" латински букви от модела).

Забавното е че ако изкуствено увелича резолюцията (софтуерно скалирам от 640x480 до 1280x960 например), разпознаването ни става още по-точно, което не е много очакван резултат и трябва да разбера защо става. Но на практика очаквам от HD камера още по-добри резултати. От near-IR камера с добра подсветка на сцената, цялата тази патаклама е абсолютно реална и работи и на светло и на тъмно и не яде особено много изчислителни ресурси.

Което е забавно, сега се замислих как може да се cheat-ва. Номерата с фолиото и спрейовете дето отразяват силно IR спектъра сигурно работи, но се замислям за по-интелигентни решения. Според мен съвсем малки "видоизменения" към номера (постигнати с лепенка черно фолио върху номера) които визуално за човек не са голям проблем, за автоматичното разпознаване могат да се окажат достатъчно голям проблем. Стига разбира се комерсиалните системи да ползват и те SVM статистически модели, а не някакъв друг подход, който не може да се излъже така.


Друго което ми хрумна, още по-забавно - обикновено емблемата на производителя на колата е някъде много близо до регистрационния номер. Можем да тренираме спокойно SVM модел с HOG хистограми и за емблемата. Така на видео няма само да откриваме регистрационни номера, би било доста забавно примерно "черен форд CA1234TP" или "зелен фиат РР5432РА".  Няма да е много голяма играчка и според мен е напълно постижимо. Вероятно има доста криви модели коли, където ще е трудно с прости евристики да докараме нещата и където ще имаме кофти hit rate, но пък по мои наблюдения в повечето случаи би трябвало да мине номера. Ще започна да се оглеждам повече докато шофирам за работа и обратно.
Активен

"Knowledge is power" - France is Bacon

4096bits

  • Напреднали
  • *****
  • Публикации: 6152
    • Профил
Re: OpenCV / обучаване на Haar cascade класификатори
« Отговор #100 -: Jun 03, 2015, 21:51 »
Сега е момента да пуснеш кода. Ще му намерим приложение.   ;D
Аз искам python, че там разбрах, че може да се работи с числа с всякаква бройка цифри, стига да има достатъчно памет. Трябва ми за едни сметки с много големи числа. 'C' не съм пипал от години и ще ми трябва един период на опресняване. А и нещо gcc ми изписва, че някакви библиотеки ми липсвали. Дали още се наричат така, не зная. iostream.h например. Май не съм инсталирал нещо. Тея библиотеки не съм ги търсил още, но ... Ще изчакат няколко дена

Добре! Редакция няма да правя, но...
Оказа се, че от '98-ма година, вече няма iostream.h, а се декларира само iostream
Също се оказа, че не мога в C++ да използвам просто cout, а трябва преди това да извикам веднага след декларациите using std::cout;
Та тестовата програмка тръгна. Са остава да разбера, колко големи числа може да поддържа С.
« Последна редакция: Jun 04, 2015, 01:58 от 4096bits »
Активен

As they say in Mexico, "Dasvidaniya!" Down there, that's two vidaniyas.

4096bits

  • Напреднали
  • *****
  • Публикации: 6152
    • Профил
Re: OpenCV / обучаване на Haar cascade класификатори
« Отговор #101 -: Jun 04, 2015, 20:13 »
Как в Python да му кажа, къде е Tkinter, защото вика, че няма такъв модул?
Активен

As they say in Mexico, "Dasvidaniya!" Down there, that's two vidaniyas.

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: OpenCV / обучаване на Haar cascade класификатори
« Отговор #102 -: Jun 05, 2015, 00:56 »
Някъде най-отгоре просто нашиваш using namespace std и тогава няма да пишеш std::cout вместо cout.

C подържа толкова големи числа, колкото е разредността на машината и в зависимост от използваният тип и дали е signed. По стандарт обаче, int е 32-битов и на x86_64 и ако ти трябва нещо по-голямо от ~2 милиарда (signed) / ~4 милиарда (unsigned), тогава се ползва long. Кодът не е portable и ще има драми на 32-битова система.

Ако ти трябват сметки с големи числа, тогава ползваш някаква bignum библиотека като gmp.

Що се отнася до TKinter, нямам идея. Сигурен ли си че е инсталиран? Питон-а коя версия е (2.x? 3?)

Активен

"Knowledge is power" - France is Bacon

4096bits

  • Напреднали
  • *****
  • Публикации: 6152
    • Профил
Re: OpenCV / обучаване на Haar cascade класификатори
« Отговор #103 -: Jun 05, 2015, 02:18 »
Инсталиран е. Python 3.4. Пуснах find да търси и намерих някаква папка мисля, но не зная как да му го посоча къде е. В /usr/lib/python3.4/tkinter но намери. Ами трябват ми много големи числа. Милиардите ще са като едно и две. Също и ще трябва да видя, как да го накарам да ползва всички ядра, че ще сгъна откъм време.
Активен

As they say in Mexico, "Dasvidaniya!" Down there, that's two vidaniyas.

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: OpenCV / обучаване на Haar cascade класификатори
« Отговор #104 -: Jun 05, 2015, 03:00 »
Ем значи import tkinter.

Threading-а в питон е пълен ташак, да го имаш предвид когато решиш да "ползваш ядрата". Ако си свикнал с pthreads специално.


Апропо, трябва да легна да спя най-накрая, досега съм тренирал невронни мрежи (multi-label перцептрон). Мързи ме да пиша всичко което забелязах, но невронните мрежи няма как да заменят SVM класификатора, тъй като при тези зададени условия и брой samples с които тренираме модела, работят доста по-зле. И това трудно ще се промени като се замисля, единственото предимство им е че могат динамично да се дообучават - късмет с SVM в това отношение. Та в крайна сметка засега използвам комбинация от SVM и невронна мрежа - ако SVM ми открие буква, тогава гледам петте най-добри кандидата от класификатора с невронната мрежа с най-добър резултат и ако е там, вземам предвид резултата от SVM, в противен случай вземам най-добрия резултат от MLP. Получава се това:

https://t.co/LYWIf6EsPL

Работи доволно коректно (сцената е гадна, моята идея за ANPR имплементация изначално включваше презюмпцията за статична камера, където сцените не се променят много). Обаче нищо идва безплатно, както работи коректно, така тук вземаме предвид само разпознатите номера където двата класификатора в известен смисъл постигат "съгласие". Като резултат, само когато номерът е достатъчно близо до камерата или условията са достатъчно сгодни, обявяваме номера за разпознат. Със статична камера, може доста да се "олабят" условията и да имаме същата успеваемост, но с движеща се такава където осветлението и ъглите под които гледаме регистрационните табели бързо се променят....по-добре да играем на сигурно.


Активен

"Knowledge is power" - France is Bacon

Подобни теми
Заглавие Започната от Отговора Прегледи Последна публикация
OpenCV или libjpeg проблем
Общ форум
shoshon 0 2357 Последна публикация Jun 22, 2009, 22:02
от shoshon
OpenCV - Help
Web development
taloveca 0 2330 Последна публикация Jan 27, 2015, 20:06
от taloveca
Инсталиране на OpenCV
Хардуерни и софтуерни проблеми
4096bits 1 2528 Последна публикация Jan 23, 2017, 20:58
от remotexx
Обработка на снимка с opencv
Хардуерни и софтуерни проблеми
gosho987 9 4173 Последна публикация Dec 07, 2017, 17:52
от 4096bits