初识SVM(验证码识别)
2016-10-22 14:22
295 查看
之前读了一堆关于SVM的论文,最近终于开始用opencv的SVM来实战了,事实证明果然不能停留于理论,真正实践又花了一定时间,把自己的历程记录如下:
首先来看一下我的main函数:
由于是第一次写SVM的代码,刚开始写的很乱,后来自己又整理了一下,大致就分为如上流程.
img_path存的是图片的路径,img_catg存的是图片对应的label,然后就先回到loadCatePath函数:
我的图片存放在多个文件夹下,文件夹名称从1、2、3一直到9,filename是公共目录,因此我们就可以用如上的方法实现依次读取文件夹,并用对应的label给图片“赋值”。
生成测试数据部分就因人而异了,针对各项目预处理方法都不同,就不多说,然后是生成XML模型部分:
都是调用了ML.h中的方法,那几个参数具体的功能还没测试过,之后需要多看一下,最后通过svm.train和svm.svm就在对应路径下生成了xml文件。
既然模型有了,接下来就可以针对我们自己的图片进行测试了:
这里有几个showImage、grayImage等函数,看名字就知道意思了,重点是在drawContours这里,将原
4000
图和处理后的二值图传递过去,因为我这里做的是验证码识别,用到了分割,这一部分的实现过程如下:
以上即为我与SVM的第一次亲密接触,接下来还有许多研究的机会,希望能有更多进展,最后附上我的结果图:
首先来看一下我的main函数:
int main() { Mat data_mat, res_mat; Mat res; vector<string> img_path; vector<int> img_catg; int nLine = 0; //loadCatePath(img_path, img_catg, nLine); //生成测试数据 //createData(img_path, data_mat, res_mat, res, nLine); //生成xml模型 //createXML(img_path, img_catg, data_mat, res_mat, res, nLine); //测试 testSVM(); //system("pause"); return 0; }
由于是第一次写SVM的代码,刚开始写的很乱,后来自己又整理了一下,大致就分为如上流程.
img_path存的是图片的路径,img_catg存的是图片对应的label,然后就先回到loadCatePath函数:
void loadCatePath(vector<string> &img_path, vector<int> &img_catg, int &nLine) { string buf; char c[10]; for (int i = 2; i < 10; ++i) { _itoa(i, c, 10); string tmp(c); string addre = filename + tmp + "/trainpath.txt"; ifstream svm_data(addre); while (svm_data) { if (getline(svm_data, buf)) { nLine++; img_catg.emplace_back(i); img_path.emplace_back(buf); } } svm_data.close(); } }
我的图片存放在多个文件夹下,文件夹名称从1、2、3一直到9,filename是公共目录,因此我们就可以用如上的方法实现依次读取文件夹,并用对应的label给图片“赋值”。
生成测试数据部分就因人而异了,针对各项目预处理方法都不同,就不多说,然后是生成XML模型部分:
void createXML(vector<string> &img_path, vector<int> &img_catg, Mat &data_mat, Mat &res_mat, Mat &res, int nImgNum) { Mat trainImg = Mat::zeros(IMGHEIGHT, IMGWIDTH, CV_8UC3); int hogImgWidht = 64, hogImgHeight = 64, n; for (string::size_type i = 0; i < img_path.size(); ++i) { res = imread(img_path[i].c_str(), 1); cout << " processing " << img_path[i].c_str() << endl; resize(res, trainImg, cv::Size(hogImgWidht, hogImgHeight), 0, 0, INTER_CUBIC); HOGDescriptor *hog = new HOGDescriptor(cvSize(hogImgWidht, hogImgHeight), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 9); vector<float> descriptors; hog->compute(trainImg, descriptors, Size(1, 1), Size(0, 0)); if (i == 0) { data_mat = Mat::zeros(nImgNum, descriptors.size(), CV_32FC1); } cout << "HOG dims: " << descriptors.size() << endl; n = 0; for (vector<float>::iterator iter = descriptors.begin(); iter != descriptors.end(); ++iter) { data_mat.at<float>(i, n) = *iter; n++; } res_mat.at<float>(i, 0) = img_catg[i]; cout << " end processing " << img_path[i].c_str() << " " << img_catg[i] << endl; } CvSVM svm; CvSVMParams param; CvTermCriteria criteria; criteria = cvTermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON); param = CvSVMParams(CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria); svm.train(data_mat, res_mat, Mat(), Mat(), param); svm.save("F:/compiler/opencv/forfun/SVM_DATA.xml"); }
都是调用了ML.h中的方法,那几个参数具体的功能还没测试过,之后需要多看一下,最后通过svm.train和svm.svm就在对应路径下生成了xml文件。
既然模型有了,接下来就可以针对我们自己的图片进行测试了:
void testSVM() { IplImage *srcImg = cvLoadImage("D:\\other\\verifycode2\\2835.jpg"); showImage("2835", srcImg); IplImage *grayImg = cvCreateImage(cvGetSize(srcImg), IPL_DEPTH_8U, 1); //灰度 grayImage(srcImg, grayImg); binary(grayImg); cvSmooth(grayImg, grayImg, CV_MEDIAN); drawContours(srcImg, grayImg); cvReleaseImage(&srcImg); cvReleaseImage(&grayImg); }
这里有几个showImage、grayImage等函数,看名字就知道意思了,重点是在drawContours这里,将原
4000
图和处理后的二值图传递过去,因为我这里做的是验证码识别,用到了分割,这一部分的实现过程如下:
CvSeq* contours = NULL; CvMemStorage* storage = cvCreateMemStorage(0); cvFindContours(grayImg, storage, &contours, sizeof(CvContour), CV_RETR_EXTERNAL); int count = 0; int idx = 0; int tempCount = 0; cvSeqSort(contours, cmp_func); int z = 0; vector<float> descriptors; vector<CvRect> v; for (CvSeq* c = contours; c != NULL; c = c->h_next) { v.emplace_back(cvBoundingRect(c, 0)); } sort(v.begin(), v.end(), mycmp); for (int i = 0; i < v.size(); ++i) { CvRect rc = v[i]; if (rc.height > srcImg->width / 10) { cvDrawRect(srcImg, cvPoint(rc.x, rc.y), cvPoint(rc.x + rc.width, rc.y + rc.height), CV_RGB(100, 100, 100)); count++; IplImage* resImg = cvCreateImage(cvSize(rc.width, rc.height), srcImg->depth, srcImg->nChannels); cvSetImageROI(srcImg, rc); cvCopyImage(srcImg, resImg); cvResetImageROI(srcImg); Mat dstImg = (Mat)resImg; resize(dstImg, dstImg, Size(64, 64)); //测试部分 CvSVM svm; svm.load("SVM_DATA.xml"); HOGDescriptor *hog = new HOGDescriptor(cvSize(64, 64), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 9); vector<float>descriptors;//结果数组 Mat trainImg = Mat::zeros(64, 64, CV_8UC3); resize(dstImg, trainImg, cv::Size(64, 64), 0, 0, INTER_CUBIC); hog->compute(trainImg, descriptors, Size(1, 1), Size(0, 0)); //调用计算函数开始计算 Mat SVMtrainMat = Mat::zeros(1, descriptors.size(), CV_32FC1); int n = 0; for (vector<float>::iterator iter = descriptors.begin(); iter != descriptors.end(); iter++) { SVMtrainMat.at<float>(0, n) = *iter; n++; } int ret = svm.predict(SVMtrainMat); cout << ret; } cvReleaseMemStorage(&storage); }
以上即为我与SVM的第一次亲密接触,接下来还有许多研究的机会,希望能有更多进展,最后附上我的结果图:
相关文章推荐
- Fastcv——机器学习SVM初识
- SVM熟练到精通1:初识SVM
- 初识验证码以及较为简单的验证码识别 (python)
- 初识SVM
- SVM验证码识别,提供源程序下载。
- 机器学习之初识SVM
- 初识J2ME
- 初识linux之LEMP
- 初识Vulkan
- 初识ZooKeeper与集群搭建实例
- 《Python数据分析与挖掘实战》第9章——svm
- 初识XML
- SVM (support vector machine) 小小结
- 支持向量机通俗导论(理解SVM的三层境界)
- CSS网页布局初识
- 逻辑回归和SVM的区别
- 初识FileSystemObject
- SVM(2)OpenCV库函数解读
- Redis入门很简单之四【初识Jedis】
- log4j-初识