我正在使用OpenCV和LibSVM开发一个手写字符识别系统。我已经提取了14个特征用于特征向量,包括胡不变量矩、仿射不变量矩、角点数量等。对于每个字符,我使用了5个样本(例如,对于字母”A”,有5种不同类型的”A”)。我知道5个样本是不够的,但目前我每个字符只有5个样本。
我使用了OpenCV文档中的基本线性SVM示例。我的问题是,我能否直接使用该文档示例来达到我的目的。我读到了一些使用多类SVM的OCR系统。我的应用是否需要这样的多类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;
回答:
你的标签设置有误。你定义了180个独特的标签,但你只有26个类别的数据。标签的长度应该是180,但只应包含1到26的值(任何26个不同的值都可以),顺序应与mattrainingDataMat中字符的顺序一致。
你需要每个字母大约5000个样本,而不是仅仅5个。你可以先使用MNIST手写数字数据集,直到你有合适的数据。
你的代码似乎是在训练一个SVM来识别单个字符。你不应该这样做,因为训练SVM可能需要很长时间。你应该单独训练SVM并保存模型,以便可以重复使用,而不需要每次都重新训练。
据我所知,OpenCV中的SVM代码基于一个旧版本的Libsvm。所以我直接使用最新版本的Libsvm,而不是OpenCV版本。
此外,对于你的情况,使用RBF核几乎肯定会比线性核获得更好的准确性(尽管线性核更容易训练)。看起来你有26个类别,所以当然你需要一个多类SVM(这实际上是许多二元SVM) – Libsvm会为你处理多类问题。