【模式识别】OpenCV中使用神经网络 CvANN_MLP
OpenCV的ml模块实现了人工神经网络(Artificial Neural Networks, ANN)最典型的多层感知器(multi-layer perceptrons, MLP)模型。由于ml模型实现的算法都继承自统一的CvStatModel基类,其训练和预测的接口都是train(),predict(),非常简单。
下面来看神经网络 CvANN_MLP 的使用~
定义神经网络及参数:
可以直接定义CvANN_MLP神经网络,并设置其参数。 BACKPROP表示使用back-propagation的训练方法,RPROP即最简单的propagation训练方法。
使用BACKPROP有两个相关参数:bp_dw_scale即bp_moment_scale:
使用PRPOP有四个相关参数:rp_dw0, rp_dw_plus, rp_dw_minus, rp_dw_min, rp_dw_max:
上述代码中为其默认值。
设置网络层数,训练数据:
layerSizes设置了有三个隐含层的网络结构:输入层,三个隐含层,输出层。输入层和输出层节点数均为5,中间隐含层每层有两个节点。
create第二个参数可以设置每个神经节点的激活函数,默认为CvANN_MLP::SIGMOID_SYM,即Sigmoid函数,同时提供的其他激活函数有Gauss和阶跃函数。
使用训练好的网络结构分类新的数据:
然后直接使用predict函数,就可以预测新的节点:
完整程序代码:
结果:
============================================================
// Hand01.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/ml/ml.hpp>
#include <opencv2/contrib/contrib.hpp>
using namespace cv;
using namespace std;
int main()
{
//Setup the BPNetwork
CvANN_MLP bp;
// Set up BPNetwork's parameters
CvANN_MLP_TrainParams params;
params.train_method = CvANN_MLP_TrainParams::BACKPROP; //(Back Propagation,BP)反向传播算法
params.bp_dw_scale = 0.1;
params.bp_moment_scale = 0.1;
// Set up training data
float labels[10][2] = { { 0.9, 0.1 }, { 0.1, 0.9 }, { 0.9, 0.1 }, { 0.1, 0.9 }, { 0.9, 0.1 }, { 0.9, 0.1 }, { 0.1, 0.9 }, { 0.1, 0.9 }, { 0.9, 0.1 }, { 0.9, 0.1 } };
//这里对于样本标记为0.1和0.9而非0和1,主要是考虑到sigmoid函数的输出为一般为0和1之间的数,只有在输入趋近于-∞和+∞才逐渐趋近于0和1,而不可能达到。
Mat labelsMat(10, 2, CV_32FC1, labels);
cout << "=========================" << endl;
cout << "labelsMat = " << endl << " " << labelsMat << endl << endl;
float trainingData[10][2] = { { 11, 12 }, { 111, 112 }, { 21, 22 }, { 211, 212 }, { 51, 32 }, { 71, 42 }, { 441, 412 }, { 311, 312 }, { 41, 62 }, { 81, 52 } };
Mat trainingDataMat(10, 2, CV_32FC1, trainingData);
cout << "=========================" << endl;
cout << "trainingDataMat = " << endl << " " << trainingDataMat << endl << endl;
Mat layerSizes = (Mat_<int>(1, 5) << 2, 100, 100, 100, 2); //5层:输入层,3层隐藏层和输出层,每层均为两个perceptron
bp.create(layerSizes, CvANN_MLP::SIGMOID_SYM);//CvANN_MLP::SIGMOID_SYM ,选用sigmoid作为激励函数
bp.train(trainingDataMat, labelsMat, Mat(), Mat(), params); //训练
// Data for visual representation
int width = 512, height = 512;
Mat image = Mat::zeros(height, width, CV_8UC3);
Vec3b green(0, 255, 0), blue(255, 0, 0);
// Show the decision regions
for (int i = 0; i < image.rows; ++i)
{
for (int j = 0; j < image.cols; ++j)
{
Mat sampleMat = (Mat_<float>(1, 2) << i, j);
Mat responseMat;
bp.predict(sampleMat, responseMat);
float* p = responseMat.ptr<float>(0);
//
if (p[0] > p[1])
{
image.at<Vec3b>(j, i) = green;
}
else
{
image.at<Vec3b>(j, i) = blue;
}
}
}
// Show the training data
int thickness = -1;
int lineType = 8;
circle(image, Point(111, 112), 5, Scalar(0, 0, 0), thickness, lineType);
circle(image, Point(211, 212), 5, Scalar(0, 0, 0), thickness, lineType);
circle(image, Point(441, 412), 5, Scalar(0, 0, 0), thickness, lineType);
circle(image, Point(311, 312), 5, Scalar(0, 0, 0), thickness, lineType);
circle(image, Point(11, 12), 5, Scalar(255, 255, 255), thickness, lineType);
circle(image, Point(21, 22), 5, Scalar(255, 255, 255), thickness, lineType);
circle(image, Point(51, 32), 5, Scalar(255, 255, 255), thickness, lineType);
circle(image, Point(71, 42), 5, Scalar(255, 255, 255), thickness, lineType);
circle(image, Point(41, 62), 5, Scalar(255, 255, 255), thickness, lineType);
circle(image, Point(81, 52), 5, Scalar(255, 255, 255), thickness, lineType);
imwrite("result.png", image); // save the image
imshow("BP Simple Example", image); // show it to the user
waitKey(0);
return 0;
}