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

  • 相关阅读:
    c# 泛型(知识整理)
    [VC++]C\C++中结构体知识点强化
    [VC++]CString转化成char
    [VC++]C++中类的多态与虚函数的使用
    [C#]关于自己编写MesasgeBox
    [C#]给DataGridView里的ComboBoxCol添加SelectIndexChange事件
    [C#]用代码触发一个事件
    [C#]序列化例子
    [VC++]怎么使对话框中的按钮DISABLE和ENABLE
    [VC++]控制台程序窗口隐藏
  • 原文地址:https://www.cnblogs.com/winslam/p/10214199.html
Copyright © 2020-2023  润新知