Как да конфигурирате CvSVM за класификация на изображения в OpenCV и C++

Разработвам система за разпознаване на ръкописни знаци, използвайки OpenCV LibSVM. Извлякох 14 характеристики за вектора на характеристиките, включително Hu моменти, афинни инвариантни моменти, брой ъгли и т.н. За всеки знак използвам 5 проби (за буква "A", има 5 вида A). Знам, че 5 проби не са достатъчни, но в момента имам само 5 проби за всеки герой.

Използвам основния пример за LINEAR SVM в документацията на opencv. Проблемът ми е, мога ли да използвам този пример за документация такъв, какъвто е, за моята цел. Чел съм за OCR системи, които използват многокласови SVM. Имам ли нужда от такъв Multi-Class SVM за моето приложение. Не разбирам от това. Моля, може ли някой да обясни? Ето моят код.

имам 180 проби от цифри и английски главни букви и за една проба има 14 функции.

float labels[180][1] = {1.0, 2.0, 3.0, 4.0, 5.0, ,,,,, -> 180.0};
Mat matlabesls(180,1, CV_32FC1, labels);

Mat mattrainingDataMat(180, 14, CV_32FC1, ifarr_readtrainingdata);
CvSVMParams params;

params.svm_type    = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit   = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);

CvSVM SVM;
SVM.train(mattrainingDataMat,matlabesls,Mat(),Mat(),params);

Mat matinput(1,14,CV_32FC1,ifarr_testarray);
is_recognizedcharacter= SVM.predict(matinput);

return is_recognizedcharacter;

person Heshan Sandeepa    schedule 26.05.2013    source източник


Отговори (1)


Настройката на вашите етикети е неправилна. Дефинирали сте 180 уникални етикета, но имате само 26 класа данни. Етикетите трябва да са с дължина 180, но трябва да съдържат само стойностите 1..26 (всеки 26 отделни стойности са подходящи) в ред, който е в съответствие с реда на знаците в mattrainingDataMat.

Ще ви трябват повече от 5000 проби от всяка буква, а не само 5. Можете да започнете с набора данни от ръкописни цифри на MNIST, докато получите правилните данни.

Вашият код изглежда обучава svm да разпознава само 1 знак. Не трябва да го правите така, защото може да отнеме много време за обучение на svm. Трябва да обучите svm отделно и да запазите модела, така че да може да се използва повторно, без да се налага да обучавате отново всеки път.

Разбирам, че svm кодът в OpenCV е базиран на стара версия на Libsvm. Така че просто използвам най-новата версия на libsvm директно, а не OpenCV версията.

Също така, за вашия случай почти сигурно ще получите много по-добра точност с RBF ядро, отколкото линейното ядро ​​(въпреки че линейното е по-лесно за обучение). Изглежда, че имате 26 класа, така че, разбира се, имате нужда от многокласов SVM (което всъщност е само много двоични SVM) - Libsvm се справя с многокласовия проблем вместо вас.

person Bull    schedule 26.05.2013
comment
здравейте, много ви благодаря, че обмислихте въпроса ми. променям кода, както следва. имам 36 класа (26 букви, 10 цифри). В момента използвам само 5 проби (докато добия ясна представа). за един клас има 5 проби и за една проба има 14 характеристики. тогава за един клас има 70 функции (5 * 14). това ли имаш предвид?? моля, помогнете .. 'float labels[36][1] = {1.0, 2.0, ... -› 36.0}; Mat matlabesls(36,1, CV_32FC1, етикети) Mat mattrainingDataMat(36, 70, CV_32FC1, ifarr_readtrainingdata);' - person Heshan Sandeepa; 26.05.2013
comment
Ако вашите данни се състоят от функциите за 3 примера за „A“, 2 за „C“ и 3 за „5“ (в този ред), тогава вашите етикети ще бъдат „float labels[7][1] ={11.0, 11.0, 11.0, 13.0,13,0, 5.0, 5.0, 5.0}, като се приеме, че 0.0..9.0 се използват за етикетиране от '0' до '9' и 11.0..35.0 се използват за етикетиране на 'A'..'Z'. Ако редът на вашите данни е бил объркан, етикетите трябва да бъдат смесени, за да съвпадат. Етикетите указват на SVM от какво е извадка всеки елемент от данни. - person Bull; 26.05.2013
comment
благодаря много, разбирам за етикетирането. можете ли да ми кажете къде е многокласовият SVM тук. чувствам, както казахте, има 3 11.0, 2 13.0 ... и т.н. това нарича ли се MultiClass SVM?? - person Heshan Sandeepa; 26.05.2013
comment
Ако имате само 2 етикета, да речем 0 и 1, или -1 и 1, тогава ще бъде двоичен svm. Ако предоставите повече от 2 различни стойности, тогава linsvm (което opencv използва) автоматично обучава много двоични svms и комбинира резултатите, така че да имате многокласов класификатор. Действителният svm алгоритъм е двоичен по природа, той просто търси хиперравнина, която ще раздели вашите данни на два набора (в идеалния случай с всички етикети във всеки набор еднакви). Ако вашите данни се състоеха само от две "А" и три "С", вие щяхте да имате "float labels[5][1] ={11.0, 11.0, 13.0,13.0 13.0} и това ще ви даде двоичен svm. - person Bull; 26.05.2013
comment
@user2151446- k тогава ще конфигурирам моя код и ще наблюдавам изхода. Благодаря ви много за вашата помощ и вашите усилия във въпроса ми.HND - person Heshan Sandeepa; 26.05.2013