opencv的svm学习_字符识别

简介

  这是基于svm实现字符识别,不过只是个大概模板,需要能够准确识别,需要的训练样本太多,没去收集。


代码讲解


具体代码

[cpp]  view plain  copy
  1. #include <opencv2/core/core.hpp>                                                                                                     
  2. #include <opencv2/highgui/highgui.hpp>  
  3. #include <opencv/cv.h>  
  4. #include <stdio.h>  
  5. #include <opencv2/ml/ml.hpp>  
  6.    
  7. using namespace cv;  
  8.    
  9. #define match_all 10  
  10. #define match_detect 10  
  11. #define pic_size 512  
  12.    
  13. int main(int argc, char* argv[]){  
  14.     const char *match_pic[match_all] = {  
  15.         "rightPic/0.bmp""rightPic/1.bmp""rightPic/2.bmp""rightPic/3.bmp""rightPic/4.bmp",  
  16.         "rightPic/5.bmp""errorPic/6.bmp""errorPic/7.bmp""errorPic/8.bmp""errorPic/9.bmp",  
  17.     };  
  18.     int i, j, k;  
  19.    
  20.     float labels[10]={1, 1, 1, 1, 1, 1, -1, -1, -1, -1};  
  21.     Mat labelsMat(10, 1, CV_32FC1, labels);  
  22.    
  23.    
  24.     float trainingData[10][pic_size];  
  25.    
  26.     for(i=0; i<match_detect; i++){  
  27.         cv::Mat mat1 = cv::imread(match_pic[i], 0);  
  28.         uchar* ptr = mat1.ptr(0);  
  29.         int length = mat1.rows * mat1.cols;  
  30.    
  31.         for(j=0; j<length; j++){  
  32.             trainingData[i][j] = (float)ptr[j];  
  33.         }     
  34.     }  
  35.     Mat trainingDataMat(10, pic_size, CV_32FC1, trainingData);  
  36.    
  37.     // Set up SVM's parameters  
  38.     CvSVMParams params;  
  39.     params.svm_type    = CvSVM::C_SVC;  
  40.     params.C            = 0.1;   
  41.     params.kernel_type = CvSVM::LINEAR;  
  42.     params.term_crit   = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);  
  43.    
  44.     // Train the SVM  
  45.     CvSVM SVM;  
  46.     SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);  
  47.    
  48.     cv::Mat mat2 = cv::imread(argv[1], 0);  
  49.     uchar* ptr2 = mat2.ptr(0);  
  50.     float testData[pic_size];  
  51.     for(k=0; k<pic_size; k++){  
  52.         testData[k] = (float)ptr2[k];  
  53.     }  
  54.     cv::Mat mat3(1, pic_size, CV_32FC1, testData);  
  55.     float response = SVM.predict(mat3);  
  56.     printf("response:%f\n", response);  
  57.     cv::imshow("SVM Simple Example", mat2);  
  58.    
  59.     waitKey(0);  
  60. }  


建立训练样本

[cpp]  view plain  copy
  1. const char *match_pic[match_all] = {  
  2.         "rightPic/0.bmp""rightPic/1.bmp""rightPic/2.bmp""rightPic/3.bmp""rightPic/4.bmp",  
  3.         "rightPic/5.bmp""errorPic/6.bmp""errorPic/7.bmp""errorPic/8.bmp""errorPic/9.bmp",  
  4.     };  
  5.     int i, j, k;  
  6.    
  7.     float labels[10]={1, 1, 1, 1, 1, 1, -1, -1, -1, -1};  
  8.     Mat labelsMat(10, 1, CV_32FC1, labels);  
  9.    
  10.    
  11.     float trainingData[10][pic_size];  
  12.    
  13.     for(i=0; i<match_detect; i++){  
  14.         cv::Mat mat1 = cv::imread(match_pic[i], 0);  
  15.         uchar* ptr = mat1.ptr(0);  
  16.         int length = mat1.rows * mat1.cols;  
  17.    
  18.         for(j=0; j<length; j++){  
  19.             trainingData[i][j] = (float)ptr[j];  
  20.         }     
  21.     }  
  22.     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的训练图片都导入到该数组中。在本例中,因为训练的样本图片都不大,所以没有取
图片的特征值,而是整个图片导入训练。


训练支持向量机

[cpp]  view plain  copy
  1.  // Set up SVM's parameters  
  2. CvSVMParams params;  
  3. params.svm_type    = CvSVM::C_SVC;  
  4. params.C            = 0.1;   
  5. params.kernel_type = CvSVM::LINEAR;  
  6. params.term_crit   = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);  
  7.   
  8. // Train the SVM  
  9. CvSVM SVM;  
  10. SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);  

  也是用函数SVM.train用之前填充的trainingDataMat进行训练。


字符识别

[cpp]  view plain  copy
  1. cv::Mat mat2 = cv::imread(argv[1], 0);  
  2. uchar* ptr2 = mat2.ptr(0);  
  3. float testData[pic_size];  
  4. for(k=0; k<pic_size; k++){  
  5.     testData[k] = (float)ptr2[k];  
  6. }  
  7. cv::Mat mat3(1, pic_size, CV_32FC1, testData);  
  8. float response = SVM.predict(mat3);  
  9. printf("response:%f\n", response);  

  分配mat2来接收,我们需要识别的图片:argv[1],然后一样的使用SVM.predict进行识别。最后如果response 返回为1,表示需要识别的图片是字符0,否则就是0-9
的其他图片。

猜你喜欢

转载自blog.csdn.net/liqiming100/article/details/78316871