SVM训练(C++实现)

在很多文献中,都把HOG和SVM结合起来使用,可以得到很不错的分类效果,SVM就不用再复习啦,就是一个线性分类器,给一个简单的图就能很好理解,

对于有标签的正样本和负样本,如果只有两个维度,也就是只有两个特征,要做的就是找到一条线,能够很好的划分为两个区域分别包含正负样本,并且这条线尽可能远离两个样本中心
在这里插入图片描述
(摘自上课的PPT)

但是这是针对二维的情况,如果扩展到多维,可能就无法找到一条线,即使找到了也可能有很多样本发生了错分,所以就需要在更高维度上考虑,高斯是最常用的。

目前我是打算将23维图像降为1维,空间信息损失实在太多啦,但是也想看看效果,就跑了跑。


一、代码及解释
	//使用SVM分类器训练  
    //设置参数的方式1
    Ptr<SVM> svm = SVM::create();
    svm->setKernel(SVM::RBF);
    svm->setType(SVM::C_SVC);
    svm->setC(10);
    svm->setCoef0(1.0);
    svm->setP(1.0);
    svm->setNu(0.5);
    svm->setTermCriteria(TermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON));

    //使用SVM学习     
    //    
    svm->train(featureVectorOfSample, ROW_SAMPLE, classOfSample);

    //保存分类器
    svm->save("Classifier.xml");
    cout<<"//-------------开始训练-------//" <<endl;
    clock_t start, end;
    start = clock();

    //使用SVM分类器训练
    //设置参数,注意Ptr的使用
    cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
    svm->setType(cv::ml::SVM::C_SVC);
    svm->setKernel(cv::ml::SVM::LINEAR);//注意必须使用线性SVM进行训练,因为HogDescriptor检测函数只支持线性检测!!!
    svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 10, FLT_EPSILON)); //迭代终止条件

    //使用SVM学习
    svm->train(samFeatureMat,cv::ml::ROW_SAMPLE, samLabelMat);

    //保存分类器(里面包括了SVM的参数,支持向量,α和rho)
    svm->save("Classifier.xml");
    end = clock();
    cout << "The obtain hog feature run time is :" << (double)(end - start) / CLOCKS_PER_SEC << "s" << endl;

    /*
    SVM训练完成后得到的XML文件里面,有一个数组,叫做support vector,还有一个数组,叫做alpha,有一个浮点数,叫做rho;
    将alpha矩阵同support vector相乘,注意,alpha*supportVector,将得到一个行向量,将该向量前面乘以-1。之后,再该行向量的最后添加一个元素rho。
    如此,变得到了一个分类器,利用该分类器,直接替换opencv中行人检测默认的那个分类器(cv::HOGDescriptor::setSVMDetector()),
    */
    //获取支持向量机:矩阵默认是CV_32F
    Mat supportVector = svm->getSupportVectors();//

    //获取alpha和rho
    Mat alpha;//每个支持向量对应的参数α(拉格朗日乘子),默认alpha是float64的
    Mat svIndex;//支持向量所在的索引
    float rho = svm->getDecisionFunction(0, alpha, svIndex);

    //转换类型:这里一定要注意,需要转换为32的
    Mat alpha2;
    alpha.convertTo(alpha2, CV_32FC1);

    //结果矩阵,两个矩阵相乘
    Mat result(1, 3780, CV_32FC1);
    result = alpha2*supportVector;

    //乘以-1,这里为什么会乘以-1?
    //注意因为svm.predict使用的是alpha*sv*another-rho,如果为负的话则认为是正样本,在HOG的检测函数中,使用rho+alpha*sv*another(another为-1)
    for (int i = 0; i < 3780; ++i)
    result.at<float>(0, i) *= -1;

    //将分类器保存到文件,便于HOG识别
    //这个才是真正的判别函数的参数(ω),HOG可以直接使用该参数进行识别
    FILE *fp = fopen("HOG_SVM.txt", "wb");
    for (int i = 0; i<3780; i++)
    {
     fprintf(fp, "%f \n", result.at<float>(0,i));
    }
    fprintf(fp, "%f", rho);
    fclose(fp);

    cout <<"真正参数得到啦"<< endl;
二、总结

如果要使用SVM进行训练的话,可能需要GPU,又或者是我维度太高了,想要二分类比较困难,这还是一个问题,等后面来解决!

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
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。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值