opencv的svm学习_字符识别

来源:互联网 发布:淘宝男装货源 编辑:程序博客网 时间:2024/06/04 17:57

简介

  这是基于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); // Set up SVM's parametersCvSVMParams 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); // Train the SVMCvSVM 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的训练图片都导入到该数组中。在本例中,因为训练的样本图片都不大,所以没有取图片的特征值,而是整个图片导入训练。


训练支持向量机

  // Set up SVM's parametersCvSVMParams 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); // Train the SVMCvSVM 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的其他图片。
0 0