SVM C++ 实现

      去年的时候,使用过 C++  版本的SVM 实现过基于无人机的道路检测,但是当时,对博大精深的 SVM 只是了解皮毛。最近,对 SVM 的基本公式及相关变体的公式,重新推导了一遍,并且分别用 Python 和 C++ 实现了一遍。此文,是用 C++ 实现的。

       SVM 公式的推导是需要掌握的,其实,如果一步一步地推导,基本公式是不难推导的,比如目标函数啊,拉格朗日乘子法, 以及涉及的对偶问题、KKT 条件、SMO 算法等。当进一步往下推导,比如 核函数、软间隔以及正则化等,需要点耐心去理解。

      数据集: http://download.csdn.net/download/wz2671/10172405

main.cpp

#include <Windows.h>  
#include "SVM.h"  
#include "matrix.h"  
#include "mat.h"  
#include <iostream>  
#pragma comment(lib, "libmat.lib")  
#pragma comment(lib, "libmx.lib")  
using namespace std;  
  
const int fn = 13;  
const int sn1 = 59;  
const int sn2 = 71;  
const int sn3 = 48;  
const int sn = 178;  
  
int readData(double* &data, double* &label)  
{  
    MATFile *pmatFile = NULL;  
    mxArray *pdata = NULL;  
    mxArray *plabel = NULL;  
  
    int ndir;//矩阵数目  
             //读取数据文件  
    pmatFile = matOpen("wine_data.mat", "r");  
    if (pmatFile == NULL) return -1;  
    /*获取.mat文件中矩阵的名称 
    char **c = matGetDir(pmatFile, &ndir); 
    if (c == NULL) return -2; 
    */  
    pdata = matGetVariable(pmatFile, "wine_data");  
    data = (double *)mxGetData(pdata);  
    matClose(pmatFile);  
    //读取类标  
    pmatFile = matOpen("wine_label.mat", "r");  
    if (pmatFile == NULL) return -1;  
    plabel = matGetVariable(pmatFile, "wine_label");  
  
    label = (double *)mxGetData(plabel);  
    matClose(pmatFile);  
  
}  
  
int main()  
{  
    doubl *data ;  
    double *label;  
    readData(data, label);  
  
    //需要注意从.mat文件中读取出的数据按列存储  
    double *d;  
    double *l;  
    SVM svm;  
      
    //第一组数据集与第二组数据集 预处理  
    l = new double[sn1 + sn2];  
    for(int i=0; i<sn1+sn2; i++)  
    {  
        if (fabs(label[i] - 2)<1e-3) l[i] = -1;  
        else l[i] = 1;  
    }  
    d = new double[(sn1 + sn2)*fn];  
    for (int i = 0; i < fn; i++)  
    {  
        for (int j = 0; j < sn1+sn2; j++)  
        {  
            d[j*fn + i] = data[i*sn + j];  
        }  
    }  
    /* 
    for (int i = 0; i < sn1 + sn2; i++) 
    { 
        for (int j = 0; j < fn; j++) 
        { 
            cout << d[i*fn + j] << ' '; 
        } 
        cout << endl; 
    } 
    */  
    svm.initialize(d, l, sn1+sn2, fn);  
    svm.SMO();  
    cout << "数据集1和数据集2";  
    svm.show();  
    delete l;  
    delete d;  
      
    //第二组数据集与第三组数据集  
    l = new double[sn2 + sn3];  
    for (int i = sn1; i < sn1 + sn2 + sn3; i++)  
    {  
        if (fabs(label[i] - 2) < 1e-3) l[i-sn1] = 1;  
        else if (fabs(label[i] - 3) < 1e-3) l[i-sn1] = -1;  
    }  
    d = new double[(sn2 + sn3)*fn];  
    for (int i = 0; i < fn; i++)  
    {  
        for (int j = sn1; j < sn; j++)  
        {  
            d[(j - sn1)*fn + i] = data[i*sn + j];  
        }  
    }  
      
    svm.initialize(d, l , sn2+sn3, fn);  
    svm.SMO();  
    cout << "\n数据集2和数据集3";  
    svm.show();  
    delete l;  
    delete d;  
      
    //第一组数据集和第三组数据集  
    l = new double[sn1 + sn3];  
    for (int i = 0; i < sn1 + sn2 + sn3
  • 14
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
HOG特征检测是一种基于梯度方向直方图的目标检测算法,可以用于人脸检测、行人检测等场景。下面是HOG特征检测+svmC++实现步骤: 1. 加载正负样本数据集并提取HOG特征 ```c++ #include <opencv2/opencv.hpp> #include <iostream> #include <fstream> #include <vector> using namespace std; using namespace cv; int main() { // 加载正负样本数据集 vector<Mat> pos_samples, neg_samples; string pos_path = "pos_samples/"; string neg_path = "neg_samples/"; for (int i = 0; i < 100; i++) { string img_name = pos_path + to_string(i) + ".jpg"; Mat img = imread(img_name, IMREAD_GRAYSCALE); pos_samples.push_back(img); } for (int i = 0; i < 100; i++) { string img_name = neg_path + to_string(i) + ".jpg"; Mat img = imread(img_name, IMREAD_GRAYSCALE); neg_samples.push_back(img); } // 提取HOG特征 HOGDescriptor hog(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9); vector<float> descriptors; vector<vector<float>> pos_descriptors, neg_descriptors; for (int i = 0; i < pos_samples.size(); i++) { hog.compute(pos_samples[i], descriptors); pos_descriptors.push_back(descriptors); } for (int i = 0; i < neg_samples.size(); i++) { hog.compute(neg_samples[i], descriptors); neg_descriptors.push_back(descriptors); } return 0; } ``` 2. 将HOG特征转换为svm的训练数据 ```c++ // 将HOG特征转换为svm的训练数据 Mat train_data; Mat train_label; for (int i = 0; i < pos_descriptors.size(); i++) { Mat row = Mat(pos_descriptors[i]).reshape(1, 1); train_data.push_back(row); train_label.push_back(1); } for (int i = 0; i < neg_descriptors.size(); i++) { Mat row = Mat(neg_descriptors[i]).reshape(1, 1); train_data.push_back(row); train_label.push_back(-1); } ``` 3. 训练svm模型并保存 ```c++ // 训练svm模型并保存 Ptr<ml::SVM> svm = ml::SVM::create(); svm->setType(ml::SVM::C_SVC); svm->setKernel(ml::SVM::LINEAR); svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6)); svm->train(train_data, ml::ROW_SAMPLE, train_label); svm->save("svm_model.xml"); ``` 4. 加载svm模型并进行目标检测 ```c++ // 加载svm模型并进行目标检测 Ptr<ml::SVM> svm = ml::StatModel::load<ml::SVM>("svm_model.xml"); HOGDescriptor hog(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9); Mat img = imread("test.jpg", IMREAD_GRAYSCALE); vector<Rect> found; vector<float> descriptors; hog.compute(img, descriptors); Mat row = Mat(descriptors).reshape(1, 1); float result = svm->predict(row); if (result == 1) { found.push_back(Rect(0, 0, 64, 128)); } hog.detectMultiScale(img, found, 0, Size(8, 8), Size(0, 0), 1.05, 2); for (int i = 0; i < found.size(); i++) { rectangle(img, found[i], Scalar(0, 0, 255), 2); } imshow("result", img); waitKey(0); ``` 以上就是HOG特征检测+svmC++实现步骤。需要注意的是,opencv中的svm模型只支持二分类,因此在本例中将正样本标签设为1,负样本标签设为-1。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值