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,操作更方便哦


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM