【OpenCV3.3】SVM与字符分类示例
来源:互联网 发布:帝国cms快速仿站 编辑:程序博客网 时间:2024/06/14 16:28
SVM,全称Support Vector Machine,即支持向量机,是机器学习中常用的分类器(同样支持向量回归),属监督式学习的一种。
在二值分类中,SVM通过寻找一个 决策最优分类超平面 来尽可能地将两类样本分开(最大分类间隔)并作为分类的判据,以期得到较强的泛化能力,我们所指的训练(train)主要就是寻找这个超平面。如果你看过相关推导,会发现原本复杂的问题被一步步等价,引入拉格朗日继而巧妙的转到凸优化及对偶问题的求解上,数学的力量令人叹为观止。
一般而言SVM是二值分类器,但是我们可以通过增加多个分类器来完成N分类,自然如何组织这些分类器也是一个优化问题。目前存在的多类判别方法有1-V-R、1-V-1、有向无环图(DAG-SVMS)、决策树方法、纠错输出编码法(ECOC)等。
OpenCV的SVM实现基于LIBSVM v2.6,而目前 LIBSVM 的最新版本是3.22,所以如果你深度依赖于SVM,建议使用LIBSVM,相比OpenCV其无论从更新频度还是支持范围都有较大优势,值得注意的是两者还是有些细微差别,不能无缝迁移。
下面是一个SVM字符分类示例:
#include "stdafx.h"#define DATA_DIR "D:\\OpenCV\\bin\\toy_data\\"//-------------------------------------------------------------------------INT WINAPI WinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPSTR, _In_ INT){cv::ipp::setUseIPP(true);// 如果SVM模型数据svm.txt存在,则从文件读取;否则加载训练数据进行训练cv::Ptr<cv::ml::SVM> &&svm = cv::ml::SVM::create();cv::FileStorage cf(DATA_DIR "svm.txt", cv::FileStorage::READ);if (cf.isOpened()) {//svm = svm->load(DIR "svm.txt");svm->read(cf.getFirstTopLevelNode());cf.release();} else {// 加载训练数据,DATA_DIR目录下所有的 [0-9][a-z].pngcv::Mat sample;cv::Mat label(cv::Size(0, 0), CV_32SC1); // 注意这里和2.x区别,3.x必须使用CV_32S,原因后面会说char filename[] = { DATA_DIR "$$.png" };char *varchar = strchr(filename, '$');for (char num = '0'; num <= '9'; ++num) {varchar[0] = num;for (char alpha = 'a'; alpha < 'z'; ++alpha) {varchar[1] = alpha;cv::Mat &&img = cv::imread(filename, cv::IMREAD_GRAYSCALE);if (img.dims > 0) {// 归一化, 一般认为能加快参数优化时的收敛速度、平衡模型权重等cv::normalize(img, img, 1., 0., cv::NormTypes::NORM_MINMAX, CV_32FC1);// 但如果你的数据量级本身相差不大,也可以不归一化直接convertTo即可//img.convertTo(img, CV_32FC1);sample.push_back(img.reshape(0, 1));label.push_back<int>(num); // 注意push_back有模版重载,可能意外改变Mat类型} //if} //for} //forcv::Ptr<cv::ml::TrainData> &&trainDataSet = cv::ml::TrainData::create(sample, cv::ml::ROW_SAMPLE, label);// 设置参数,仅作为示例// svm->setType(cv::ml::SVM::C_SVC);// svm->setKernel(cv::ml::SVM::LINEAR);// svm->setC(0.01);// svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS, 1000, FLT_EPSILON));// svm->train(trainDataSet);// 有时候会出现过拟合、欠拟合现象,排除训练数据影响的情况下一般就是参数问题了,可以使用trainAuto来进行参数优化svm->trainAuto(trainDataSet);// 如果想让部分参数不进行优化,可以使用*cv::ml::ParamGrid::create(0, 0, 0)代替相应Grid默认值,如下不对C进行优化://svm->trainAuto(trainDataSet, 10, *cv::ml::ParamGrid::create(0, 0, 0));svm->save(DATA_DIR "svm.txt");} //ifcv::Mat &&tk = cv::imread(DATA_DIR "9b.png", cv::IMREAD_GRAYSCALE); cv::normalize(tk, tk, 1., 0., cv::NormTypes::NORM_MINMAX, CV_32FC1);//tk.convertTo(tk, CV_32FC1);float r = svm->predict(tk.reshape(0, 1));char c[] = { static_cast<char>(r), 0 };OutputDebugStringA(c);return 0;}
上述程序运行后会在IDE调试窗口输出9。我的部分训练数据如下(来自MSPAINT,每个样本都是8x8的二值图像):
代码中提到标签类型在3.x版本应该使用CV_32S(OpenCV 2.x版本使用CV_32F),否则会产生错误,文档没有提及原因,但看了模块源码,似乎是有意的`bug`:当模型使用C_SVC或NU_SVC,并且标签、样本数量一致时 ,label使用CV_32FC1会出现错误,原因是C_SVC会使用TrainData::getTrainNormCatResponses,而normCatResponses是空的(未被初始化),因为\modules\ml\src\data.cpp第320行
if( noutputvars == 1 ) varType.at<uchar>(ninputvars) = (uchar)(responses.type() < CV_32F ? VAR_CATEGORICAL : VAR_ORDERED);此时CV_32F会导致打上VAR_ORDERED标志,从而在第406行跳过了preprocessCategorical对normCatResponses的处理
if( noutputvars > 0 && varType.at<uchar>(ninputvars) == VAR_CATEGORICAL ){ preprocessCategorical(responses, &normCatResponses, labels, &counters, sortbuf); Mat(labels).copyTo(classLabels); Mat(counters).copyTo(classCounters);}从而导致断言data != NULL失败。
- 【OpenCV3.3】SVM与字符分类示例
- SVM 多分类 -SVM分类opencv3.0源代码
- SVM 多分类 -SVM分类opencv3.0源代码
- SVM 多分类 -SVM分类opencv3.0源代码
- OpenCV3.2 HOG+SVM进行物体分类
- 基于SVM的分类识别 opencv3.1.0
- 文本分类与SVM
- 文本分类与SVM
- 文本分类与SVM
- svm与文本分类
- 文本分类与SVM
- 文本分类与SVM
- 文本分类与SVM
- 文本分类与SVM
- 文本分类与SVM
- opencv3.3 svm的使用
- opencv3 SVM
- SVM多分类器的实现(Opencv3,C++)
- HDU 6069 求区间[L,R]每个数的k次方的因子数之和
- 基于RandomAccessFile实现断点文件下载功能
- 【OpenCV3.3】搭建VS2017+Android开发环境
- Android 0基础从入门到精通
- tensorflow 实现rnn
- 【OpenCV3.3】SVM与字符分类示例
- HDU6077-Time To Get Up
- Python3.x安装numpy和matplotlib的问题
- 2017 暑假艾教集训 day5
- Hibernate多对多操作
- python SyntaxError: non-default argument follows default argument
- HDU.2149 Public Sale (博弈论 巴什博弈)
- Android学习笔记17-自定义控件
- 错误记录——Invalid field value for field "position".