一)机器学习概念 1.回归分析(regression analysis)是确定两种或两种以上变数间相互依赖的定量关系的一种统计分析方法,运用十分广泛。回归分析按照涉及的自变量的多少,可分为一元回归分析和多元回归分析;按照自变量和因变量之间的关系类型,可分为线性回归分析和非线性回归分析。如果在回归分析中只包括一个自变量和一个因变量,且二者的关系可用一条直线近似表示,这种回归分析称为一元线性回归分析。如果回归分析中包括两个或两个以上的自变量,且因变量和自变量之间是线性关系,则称为多元线性回归分析。 2.人工神经网络,ANN,其的学习机理是什么?简单来说,就是分解与整合。 3.SVM(支持向量机) 支持向量机(Support Vector Machine)是Cortes和Vapnik于1995年首先提出的,支持向量机在统计学习理论的VC 维理论和结构风险最小原理基础上,根据有限的样本信息在模型的复杂性(即对特定训练样本的学习精度,Accuracy)和学习能力(即无错误地识别任意样本的能力)之间寻求最佳折衷,以期获得最好的推广能力[14](或称泛化能力)。它在解决小样本、非线性及高维模式识别中表现出许多特有的优势,并能够推广应用到函数拟合等其他机器学习问题中[10]。 4.推荐算法,推荐算法的主要特征就是可以自动向用户推荐他们最感兴趣的东西,从而增加购买率,提升效益。一类是基于物品内容的推荐;另一类是基于用户相似度的推荐。目前最实用的是协同过滤算法。 5.机器学习的应用--大数据,机器学习的子类--深度学习,机器学习的父类--人工智能。 二)SVM源代码 SVM在不同的opencv版本下有不同的实现代码,我测试的代码是3.1.0。- #include "opencv2/opencv.hpp"
- #include "opencv2/imgproc.hpp"
- #include "opencv2/highgui.hpp"
- #include "opencv2/ml/ml.hpp"
- #include "opencv2/ml.hpp"
- using namespace std;
- using namespace cv;
- using namespace cv::ml;
- Mat img,image;
- Mat targetData, backData;
- bool flag = true;
- string wdname = "image";
- void on_mouse(int event, int x, int y, int flags, void* ustc); //鼠标取样本点
- void getTrainData(Mat &train_data, Mat &train_label); //生成训练数据
- void svm(); //svm分类
- int main(int argc, char** argv)
- {
- string path = "heidfk640.jpg";
- img = imread(argv[1]);
- img.copyTo(image);
- if (img.empty())
- {
- cout << "Image load error";
- return 0;
- }
- namedWindow(wdname);
- setMouseCallback(wdname, on_mouse, 0);
-
- for (;;)
- {
- imshow("image", img);
-
- int c = waitKey(0);
- if ((c & 255) == 27)
- {
- cout << "Exiting ...\n";
- break;
- }
- if ((char)c == 'c')
- {
- flag = false;
- }
- if ((char)c == 'q')
- {
- destroyAllWindows();
- break;
- }
- }
- svm();
- return 0;
- }
- //鼠标在图像上取样本点,按q键退出
- void on_mouse(int event, int x, int y, int flags, void* ustc)
- {
- if (event == CV_EVENT_LBUTTONDOWN)
- {
- Point pt = Point(x, y);
- Vec3b point = img.at<Vec3b>(y, x); //取出该坐标处的像素值,注意x,y的顺序
- Mat tmp = (Mat_<float>(1, 3) << point[0], point[1], point[2]);
- if (flag)
- {
- targetData.push_back(tmp); //加入正样本矩阵
- circle(img, pt, 2, Scalar(0, 255, 255), -1, 8); //画出点击的点
- }
- else
- {
- backData.push_back(tmp); //加入负样本矩阵
- circle(img, pt, 2, Scalar(255, 0, 0), -1, 8);
- }
- imshow(wdname, img);
- }
- }
- void getTrainData(Mat &train_data, Mat &train_label)
- {
- int m = targetData.rows;
- int n = backData.rows;
- cout << "ok :" << m << endl;
- cout << "failed:" << n << endl;
- vconcat(targetData, backData, train_data); //合并所有的样本点,作为训练数据
- train_label = Mat(m + n, 1, CV_32S, Scalar::all(1)); //初始化标注
- for (int i = m; i < m + n; i++)
- train_label.at<int>(i, 0) = -1;
- }
- void svm()
- {
- Mat train_data, train_label;
- getTrainData(train_data, train_label); //获取鼠标选择的样本训练数据
- // 设置参数
- Ptr<SVM> svm = SVM::create();
- svm->setType(SVM::C_SVC);
- svm->setKernel(SVM::LINEAR);
- // 训练分类器
- Ptr<TrainData> tData = TrainData::create(train_data, ROW_SAMPLE, train_label);
- svm->train(tData);
- Vec3b color(0, 0, 0);
- // Show the decision regions given by the SVM
- for (int i = 0; i < image.rows; ++i)
- for (int j = 0; j < image.cols; ++j)
- {
- Vec3b point = img.at<Vec3b>(i, j); //取出该坐标处的像素值
- Mat sampleMat = (Mat_<float>(1, 3) << point[0], point[1], point[2]);
- float response = svm->predict(sampleMat); //进行预测,返回1或-1,返回类型为float
- if ((int)response != 1)
- image.at<Vec3b>(i, j) = color; //将背景设置为黑色
- }
- imshow("SVM Simple Example", image);
- waitKey(55550);
- }
复制代码 三)操作步骤 1.加载图片,并显示,抓取鼠标点击事件,并获取点击位置坐标; 2.根据flag的数值来觉得是正样本,还是负样本。默认是正样本,按C键后开始抓取负样本数据; 3.‘Q’键表示抓取样本结束,开始训练识别,并显示结果。 四)运行结果和说明 看上面五组数据好像非常不错基本上可以定位好车牌的区域,其实不然,不信你自己测试一下,很多时间第四组的测试结果才是常态。 正负样本的数据采集非常重要,一个负样本被认为是正样本,其后果会非常严重。 五)总结 1.本来想要将这个程序改为NDK+Android Studio实现,只是鼠标的java程序实在搞不定,为了后面的进度干脆直接使用linux环境下的代码了。 2.关于车牌,我是从网上拿到的图片,随机使用,如果有问题请及时通知我。 |