SVM《三、核函数、数字识别、图像分类》

   有关核函数,不想多介绍,参考:https://blog.csdn.net/v_july_v/article/details/7624837

这里简单说明下,以下图二分类为例子,显然线性不可分,我们用核函数 F 将特征向量升维,至三维空间,然后很容易找一个平面将样本分割开来,如图2。

图1

 

 图2

  再比如:

 

 

1、核函数的分类

(1)线性核函数

(2)多项式核函数

(3)径向基(RBF)核函数(高斯核函数)

(4)Sigmoid核函数(二层神经收集核函数)

2、opencv320 中的核函数定义:

ml::SVM::LINEAR : 线性内核,没有任何向映射至高维空间,线性区分(或回归)在原始特点空间中被完成,这是最快的选择。

.

ml::SVM::POLY : 多项式内核:

.

ml::SVM::RBF : 基于径向的函数,对于大多半景象都是一个较好的选择:

.

ml::SVM::SIGMOID : Sigmoid函数内核:

.

  核函数的选用并没有严格数学依据,基本靠经验(基本上就是XJBS)。

 例1:识别数字

如图1:我们首先将其进行切割得到5000个样本,利用其80%的样本进行训练,剩余20%作为测试样本。

流程:提取归一化的Hog特征,训练得到xml文件(决策边界参数);预测。

 

切割程序:

 1 #include <opencv2/opencv.hpp>
 2 #include <iostream>
 3 
 4 using namespace std;
 5 using namespace cv;
 6 
 7 int main()
 8 {
 9     char ad[128] = { 0 };
10     int  filename = 0, filenum = 0;
11     Mat img = imread("digits.png");
12     Mat gray;
13     cvtColor(img, gray, CV_BGR2GRAY);
14     int b = 20;
15     int m = gray.rows / b;   //原图为1000*2000
16     int n = gray.cols / b;   //裁剪为5000个20*20的小图块
17 
18     for (int i = 0; i < m; i++)
19     {
20         int offsetRow = i*b;  //行上的偏移量
21         if (i % 5 == 0 && i != 0)
22         {
23             filename++;
24             filenum = 0;
25         }
26         for (int j = 0; j < n; j++)
27         {
28             int offsetCol = j*b; //列上的偏移量
29             sprintf_s(ad, "D:\\data_svm\\%d\\%d.jpg", filename, filenum++);
30         //    cout << ad << endl;
31             //截取20*20的小块
32             Mat tmp;
33             gray(Range(offsetRow, offsetRow + b), Range(offsetCol, offsetCol + b)).copyTo(tmp);
34             imwrite(ad, tmp);
35         }
36     }
37     return 0;
38 }

 切割完之后,图像块保存在如图的文件夹中,每个文件夹中文件索引从0-499

 

每一张图对应地址下入文本文件:myImageList1.txt 【文中文件见博客最下百度云】

假设拿出每一类中的前400个样本进行当做训练样本;新建一个文本文件 myImageLabels1.txt,写入对应每一类的标签。 

最后将测试样本图片路径写入文本文件:myImagetest1.txt

  1 //SVM多分类训练测试
  2 #include <opencv2/opencv.hpp>
  3 #include <iostream>
  4 #include <fstream>
  5 
  6 using namespace cv;
  7 using namespace std;
  8 Size imageSize = Size(64, 64);
  9 
 10 void coumputeHog(const Mat& src, vector<float> &descriptors)
 11 {
 12     HOGDescriptor myHog = HOGDescriptor(imageSize, Size(16, 16), cvSize(8, 8), cvSize(8, 8), 9);
 13     myHog.compute(src.clone(), descriptors, Size(1, 1), Size(0, 0));
 14 
 15 }
 16 
 17 int main(int argc, char** argv) {
 18     ifstream inLabels("myImageLabels1.txt"), inImages("myImageList1.txt"), inTestimage("myImagetest1.txt");
 19 
 20     string imageName;
 21     signed imageLabel;
 22     vector<Mat> vecImages;
 23     vector<int> vecLabels;
 24     //CvSVM *mySVM = new CvSVM();
 25     //CvSVMParams params = CvSVMParams();
 26     //params.svm_type = CvSVM::C_SVC;
 27     //params.kernel_type = CvSVM::LINEAR;
 28     ////params.kernel_type = CvSVM::RBF;
 29     //params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 10000, 1e-10);
 30     Ptr<ml::SVM> svm = ml::SVM::create();
 31     svm->setType(ml::SVM::C_SVC);
 32     svm->setKernel(ml::SVM::LINEAR);
 33     //svm->setDegree(0.5);
 34     svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 10000, 1e-10));
 35 
 36 
 37 
 38     vector<float> vecDescriptors;
 39 
 40 #if(1) //是否需要训练
 41     while ((inImages >> imageName) && (inLabels >> imageLabel))//读取样本和标签
 42     {
 43         Mat src = imread(imageName, 0);
 44         if (src.empty())
 45         {
 46             continue;
 47         }
 48         resize(src, src, imageSize);//归一化尺寸
 49         vecImages.push_back(src);//准备训练样本图序列
 50         vecLabels.push_back(imageLabel);//准备图序列对应的标签序列
 51     }
 52     inLabels.close();
 53     inImages.close();
 54 
 55     Mat dataDescriptors;
 56     Mat dataResponse = (Mat)vecLabels;//还可以这样强制转换?
 57     for (size_t i = 0; i < vecImages.size(); i++)
 58     {
 59         Mat src = vecImages[i];//每一张样本图
 60         Mat tempRow;
 61         coumputeHog(src, vecDescriptors);//提取Hog特征向量
 62         if (i == 0)//这里就是初始化一个 特征矩阵,行数 = 样本数; 每一行存储 每一个样本的Hog特征向量
 63         {
 64             dataDescriptors = Mat::zeros(vecImages.size(), vecDescriptors.size(), CV_32FC1);
 65         }
 66         tempRow = ((Mat)vecDescriptors).t();//转置
 67         tempRow.row(0).copyTo(dataDescriptors.row(i));//将每一个Hog特征向量保存到特征矩阵中去
 68     }
 69 
 70     //mySVM->train(dataDescriptors, dataResponse, Mat(), Mat(), params);
 71     svm->train(dataDescriptors, ml::ROW_SAMPLE, dataResponse);
 72     //string svmName = to_string(long long(88)) + "_mysvm.xml";
 73     //mySVM->save(svmName.c_str());
 74     svm->save("svm1.xml");
 75 
 76     //CvSVMParams params = mySVM->get_params();
 77 #else
 78 
 79     //mySVM->load("88_mysvm.xml");
 80     svm = ml::SVM::load("svm1.xml");
 81 #endif
 82 
 83     // 预测
 84     string testPath;
 85     while (inTestimage >> testPath)//读取每一张测试图
 86     {
 87         Mat test = imread(testPath, 0);
 88         resize(test, test, imageSize);//归一化
 89         vector<float> imageDescriptor;
 90         coumputeHog(test, imageDescriptor);//提取Hog特征
 91         Mat testDescriptor = Mat::zeros(1, imageDescriptor.size(), CV_32FC1);//类型转换
 92         for (size_t i = 0; i < imageDescriptor.size(); i++)
 93         {
 94             testDescriptor.at<float>(0, i) = imageDescriptor[i];//Hog特征赋值
 95         }
 96         //float  label = mySVM->predict(testDescriptor, false);//对当前样本进行   预测
 97                                                              //
 98         float  label = svm->predict(testDescriptor);
 99         switch (int(label))
100         {
101         case 0:
102             cout << label << " " << " = 0" << endl;
103             break;
104         case 1:
105             cout << label << " " << " = 1" << endl;
106             break;
107         case 2:
108             cout << label << " " << " = 2" << endl;
109             break;
110         case 3:
111             cout << label << " " << " = 3" << endl;
112             break;
113         case 4:
114             cout << label << " " << " = 4" << endl;
115             break;
116         case 5:
117             cout << label << " " << " = 5" << endl;
118             break;
119         case 6:
120             cout << label << " " << " = 6" << endl;
121             break;
122         case 7:
123             cout << label << " " << " = 7" << endl;
124             break;
125         case 8:
126             cout << label << " " << " = 8" << endl;
127             break;
128         case 9:
129             cout << label << " " << " = 9" << endl;
130             break;
131 
132         }
133         //cout << label << endl;
134         imshow("test image", test);
135         waitKey(0);
136     }
137 
138     inTestimage.close();
139     //delete mySVM;
140     return 0;
141 }

5000个样本训练需要一段时间,工程文件目录下会生成svm1.xml文件。按空格更换样本,打印出预测值。

 

 

例2:对飞机、蝴蝶、相机、剪刀、向日葵进行分类。

 

    略,见链接

链接:https://pan.baidu.com/s/1m6JbpGUyDFKfGldfWAYWgg
提取码:xwkx

 

 3、SVM多分类

 多分类主要涉及复杂度问题,参考 DAG SVM

链接:https://pan.baidu.com/s/15ItXi0ANQzHS8QaIb6VTkA
提取码:ccqm
复制这段内容后打开百度网盘手机App,操作更方便哦

转载于:https://www.cnblogs.com/winslam/p/10214199.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值