简介
这是基于svm实现字符识别,不过只是个大概模板,需要能够准确识别,需要的训练样本太多,没去收集。
代码讲解
具体代码
- #include <opencv2/core/core.hpp>
- #include <opencv2/highgui/highgui.hpp>
- #include <opencv/cv.h>
- #include <stdio.h>
- #include <opencv2/ml/ml.hpp>
-
- using namespace cv;
-
- #define match_all 10
- #define match_detect 10
- #define pic_size 512
-
- int main(int argc, char* argv[]){
- const char *match_pic[match_all] = {
- "rightPic/0.bmp", "rightPic/1.bmp", "rightPic/2.bmp", "rightPic/3.bmp", "rightPic/4.bmp",
- "rightPic/5.bmp", "errorPic/6.bmp", "errorPic/7.bmp", "errorPic/8.bmp", "errorPic/9.bmp",
- };
- int i, j, k;
-
- float labels[10]={1, 1, 1, 1, 1, 1, -1, -1, -1, -1};
- Mat labelsMat(10, 1, CV_32FC1, labels);
-
-
- float trainingData[10][pic_size];
-
- for(i=0; i<match_detect; i++){
- cv::Mat mat1 = cv::imread(match_pic[i], 0);
- uchar* ptr = mat1.ptr(0);
- int length = mat1.rows * mat1.cols;
-
- for(j=0; j<length; j++){
- trainingData[i][j] = (float)ptr[j];
- }
- }
- Mat trainingDataMat(10, pic_size, CV_32FC1, trainingData);
-
-
- CvSVMParams params;
- params.svm_type = CvSVM::C_SVC;
- params.C = 0.1;
- params.kernel_type = CvSVM::LINEAR;
- params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
-
-
- CvSVM SVM;
- SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);
-
- cv::Mat mat2 = cv::imread(argv[1], 0);
- uchar* ptr2 = mat2.ptr(0);
- float testData[pic_size];
- for(k=0; k<pic_size; k++){
- testData[k] = (float)ptr2[k];
- }
- cv::Mat mat3(1, pic_size, CV_32FC1, testData);
- float response = SVM.predict(mat3);
- printf("response:%f\n", response);
- cv::imshow("SVM Simple Example", mat2);
-
- waitKey(0);
- }
建立训练样本
- const char *match_pic[match_all] = {
- "rightPic/0.bmp", "rightPic/1.bmp", "rightPic/2.bmp", "rightPic/3.bmp", "rightPic/4.bmp",
- "rightPic/5.bmp", "errorPic/6.bmp", "errorPic/7.bmp", "errorPic/8.bmp", "errorPic/9.bmp",
- };
- int i, j, k;
-
- float labels[10]={1, 1, 1, 1, 1, 1, -1, -1, -1, -1};
- Mat labelsMat(10, 1, CV_32FC1, labels);
-
-
- float trainingData[10][pic_size];
-
- for(i=0; i<match_detect; i++){
- cv::Mat mat1 = cv::imread(match_pic[i], 0);
- uchar* ptr = mat1.ptr(0);
- int length = mat1.rows * mat1.cols;
-
- for(j=0; j<length; j++){
- trainingData[i][j] = (float)ptr[j];
- }
- }
- Mat trainingDataMat(10, pic_size, CV_32FC1, trainingData);
首先是定义使用了10个训练样本,在labels中,利用1和-1,将前6个分为一类,后四个分为一类。接着match_pic定义了训练样本的路径,所谓的训练样本也就是
10张图片,前面6张是字符0的图片,后面4张是其他1-9的图片。这样通过大量训练之后,就能在这个svm中将0从0-9的字符中识别出来。但是训练样本必须大。。不能
如本例这般小。
分配一个结构保存训练样本数据:trainingData[10][pic_size];将10张16X32的训练图片都导入到该数组中。在本例中,因为训练的样本图片都不大,所以没有取
图片的特征值,而是整个图片导入训练。
训练支持向量机
-
- CvSVMParams params;
- params.svm_type = CvSVM::C_SVC;
- params.C = 0.1;
- params.kernel_type = CvSVM::LINEAR;
- params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
-
-
- CvSVM SVM;
- SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);
也是用函数SVM.train用之前填充的trainingDataMat进行训练。
字符识别
- cv::Mat mat2 = cv::imread(argv[1], 0);
- uchar* ptr2 = mat2.ptr(0);
- float testData[pic_size];
- for(k=0; k<pic_size; k++){
- testData[k] = (float)ptr2[k];
- }
- cv::Mat mat3(1, pic_size, CV_32FC1, testData);
- float response = SVM.predict(mat3);
- printf("response:%f\n", response);
分配mat2来接收,我们需要识别的图片:argv[1],然后一样的使用SVM.predict进行识别。最后如果response 返回为1,表示需要识别的图片是字符0,否则就是0-9
的其他图片。