OpenCV神经网络

    xiaoxiao2021-03-25  108

    OpenCV的神经网络使用(CvANN_MLP)


    概要

    首先,我们应该知道在OpenCV中已经有了很多的分类和回归算法。其中,在ml模块中我们可以使用OpenCV自带的神经网络算法CvANN_MLP。神经网络的具体实现我就不详细介绍了,在这里我们主要是介绍CvANN_MLP的定义及如何调用。

    原文参考:http://blog.csdn.net/qq_15947787/article/category/6115133/2 、http://blog.csdn.net/xiaowei_cqu/article/details/9027617 和 http://www.cnblogs.com/farewell-farewell/p/6027888.html

    ANN – Artificial Neural Networks 人工神经网络 MLP – Multi-layer perceptrons 多重感知器

    其实,CvANN_MLP的最重要三个调用函数是 creat()、train() 和 predict();

    定义人工神经网络
    CvANN_MLP bp; // Set up BPNetwork's parameters CvANN_MLP_TrainParams params; params.train_method=CvANN_MLP_TrainParams::BACKPROP; params.bp_dw_scale=0.1; params.bp_moment_scale=0.1; //params.train_method=CvANN_MLP_TrainParams::RPROP; //params.rp_dw0 = 0.1; //params.rp_dw_plus = 1.2; //params.rp_dw_minus = 0.5; //params.rp_dw_min = FLT_EPSILON; //params.rp_dw_max = 50.;

    在这里,我们可以很清楚地了解到OpenCV实现神经网络主要使用两种训练方法: BACKPROP 与 RPROP

    创建分类器,设置网络层数
    Mat layerSizes=(Mat_<int>(1,5) << 5,2,2,2,5); //create第二个参数可以设置每个神经节点的激活函数,默认为 CvANN_MLP::SIGMOID_SYM,即Sigmoid函数 //同时提供的其他激活函数有Gauss(CvANN_mlp::GAUSSIAN)和阶跃函数 (CvANN_MLP::IDENTITY)。 bp.create(layerSizes,CvANN_MLP::SIGMOID_SYM); //CvANN_MLP::SIGMOID_SYM

    layerSizes设置了有5层的网络结构:输入层,三个隐含层,输出层。输入层和输出层节点数均为5,中间隐含层每层有两个节点。

    create第二个参数可以设置每个神经节点的激活函数,默认为CvANN_MLP::SIGMOID_SYM,即Sigmoid函数,同时提供的其他激活函数有Gauss和阶跃函数。

    训练数据
    // Set up training data float labels[3][5] = {{0,0,0,0,0},{1,1,1,1,1},{0,0,0,0,0}}; Mat labelsMat(3, 5, CV_32FC1, labels); float trainingData[3][5] = { {1,2,3,4,5},{111,112,113,114,115}, {21,22,23,24,25} }; Mat trainingDataMat(3, 5, CV_32FC1, trainingData); Mat layerSizes=(Mat_<int>(1,5) << 5,2,2,2,5); 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; bp.create(layerSizes,CvANN_MLP::SIGMOID_SYM);//CvANN_MLP::SIGMOID_SYM //CvANN_MLP::GAUSSIAN //CvANN_MLP::IDENTITY bp.train(trainingDataMat, labelsMat, Mat(),Mat(), params);

    int CvANN_MLP::train(constMat& inputs, constMat& outputs,

    constMat& sampleWeights, constMat& sampleIdx=Mat(),

    CvANN_MLP_TrainParams params=CvANN_MLP_TrainParams(), intflags=0 );

    1) inputs:输入矩阵。它存储了所有训练样本的特征。假设所有样本总数为nSamples,而我们提取的特征维数为ndims,

    则inputs是一个nSamples∗ndims的矩阵,每个样本的特征占一行。

    2) outputs:输出矩阵。我们实际在训练中,我们知道每个样本所属的种类,假设一共有nClass类。那么我们将outputs设置为

    一个nSample*nClass列的矩阵,每一行表示一个样本的预期输出结果,该样本所属的那类对应的列设置为1,其他都为0。

    比如我们需要识别0-9这10个数字,则总的类数为10类,那么样本数字“3”的预期输出为[0,0,1,0,0,0,0,0,0,0];

    3) sampleWeights:一个在使用RPROP方法训练时才需要的数据,所以这里我们不设置,直接设置为Mat()即可。

    4) sampleIdx:相当于一个遮罩,它指定哪些行的数据参与训练。如果设置为Mat(),则所有行都参与。

    5) params:这个在刚才已经说过了,是训练相关的参数。

    预测数据
    Mat image = Mat::zeros(500, 500, CV_8UC3); Vec3b white(255,255,255), black (0,0,0), gray(125,125,125); for (int i = 0; i < image.cols; i++) { for (int j = 0; j < image.rows; j++) { Mat sampleMat = (Mat_<float>(1,2) << i,j); Mat responseMat; bp.predict(sampleMat, responseMat); Point maxLoc; minMaxLoc(responseMat,NULL,NULL,NULL,&maxLoc); if (maxLoc.x == 0) image.at<Vec3b>(j, i) = white; if (maxLoc.x == 1) image.at<Vec3b>(j, i) = black; if (maxLoc.x == 2) image.at<Vec3b>(j, i) = gray; } }

    float CvANN_MLP::predict(constMat&inputs,Mat&outputs)

    图像进行特征提取,把它保存在inputs里,通过调用predict函数,我们得到一个输出向量,它是一个1*nClass的行向量,

    其中每一列说明它与该类的相似程度(0-1之间),也可以说是置信度。我们只用对output求一个最大值,就可得到结果。

    这个函数的返回值是一个无用的float值,可以忽略。

    完整代码样例一:
    //CvANN 神经网络初试 三元分类 //网址参考: http://blog.csdn.net/qq_15947787/article/details/51360287 /* #include "stdafx.h" #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/ml/ml.hpp> #include <iostream> #include <string> #include <time.h> #include <fstream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; const int COUNT = 21; //读入train数据的个数 const int DIM = 2; //输入向量的特征维数 int main() { float data[COUNT][DIM] = { 0 }; ifstream in("data.txt"); for (int i = 0; i < COUNT; i++) in >> data[i][0] >> data[i][1]; in.close(); //for (int i = 0; i < COUNT; i++) // cout << data[i][0] << " " << data[i][1] << endl; float label[COUNT][3]; ifstream in2("label2.txt"); for (int i = 0; i < COUNT; i++) in2 >> label[i][0] >> label[i][1] >> label[i][2]; in2.close(); //for (int i = 0; i < COUNT; i++) // cout << label [i][0] << " " << label[i][1] <<" "<<label[i][2]<<endl; Mat trainData(COUNT, 2, CV_32FC1, data); Mat trainLabel(COUNT, 3, CV_32FC1, label); //for (int i = 0; i < trainLabel.rows; i++) //{ // for (int j = 0; j < trainLabel.cols; j++) // cout << trainLabel.at<float>(i, j) << " "; // cout << endl; //} CvANN_MLP bp; CvANN_MLP_TrainParams param; param.term_crit = cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 10000, 0.01); param.train_method = CvANN_MLP_TrainParams::BACKPROP; param.bp_dw_scale = 0.1; param.bp_moment_scale = 0.1; Mat layerSizes = (Mat_<int>(1, 4) << 2, 8, 8 , 3); bp.create(layerSizes, CvANN_MLP::SIGMOID_SYM); //bp.create(laySizes, CvANN_MLP::GAUSSIAN); //bp.create(layerSizes, CvANN_MLP::IDENTITY); bp.train(trainData, trainLabel, Mat(), Mat(), param); bp.save("bp.xml"); Mat image = Mat::zeros(500, 500, CV_8UC3); Mat responseMat; Vec3b white(255, 255, 255), black(0, 0, 0), gray(125, 125, 125); for (int i = 0; i < image.cols; i++) { for (int j = 0; j < image.rows; j++) { Mat sampleMat = (Mat_<float>(1, 2) << i, j); bp.predict(sampleMat, responseMat); Point maxLoc; minMaxLoc(responseMat, NULL, NULL, NULL, &maxLoc); if (maxLoc.x == 0) image.at<Vec3b>(i, j) = white; //第一类 if (maxLoc.x == 1) image.at<Vec3b>(i, j) = black; //第二类 if (maxLoc.x == 2) image.at<Vec3b>(i, j) = gray; //第三类 } } cout << responseMat.rows << " " << responseMat.cols << endl; for (int i = 0; i < COUNT; i++) { Point p(data[i][0], data[i][1]); if (label[i][0] > 0) circle(image, p, 3, Scalar(255, 0, 0), -1, 8); //蓝色 if (label[i][1] > 0) circle(image, p, 3, Scalar(0, 0, 255), -1, 8); //红色 if (label[i][2] > 0) circle(image, p, 3, Scalar(0, 255, 0), -1, 8); //绿色 } imshow("result", image); waitKey(0); return 0; } */

    完整代码样例二:

    /* //CvANN 神经网络初试 测试数据集是特征维为9的癌症数据集 数据来源:E:\实验\大三\大三上\人工智能\实验五之DT&LR\数据集 //二元分类 //网址参考: http://blog.csdn.net/qq_15947787/article/details/51360287 #include "stdafx.h" #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/ml/ml.hpp> #include <iostream> #include <string> #include <time.h> #include <fstream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; const int COUNT_TRAIN = 500; //读入train数据的个数 const int COUNT_TEST = 100; const int DIM = 9; //输入向量的特征维数 int main() { //train float data[COUNT_TRAIN][DIM] = { 0 }; ifstream in("train_data.txt"); for (int i = 0; i < COUNT_TRAIN; i++) { for (int j = 0; j < DIM; j++) in >> data[i][j]; } in.close(); //for (int i = 0; i < COUNT; i++) // cout << data[i][0] << " " << data[i][1] << endl; float label[COUNT_TRAIN]; ifstream in2("train_label.txt"); for (int i = 0; i < COUNT_TRAIN; i++) in2 >> label[i]; in2.close(); //for (int i = 0; i < COUNT; i++) // cout << label[i] << endl; Mat trainData(COUNT_TRAIN, DIM, CV_32FC1, data); Mat trainLabel(COUNT_TRAIN, 1, CV_32FC1, label); //for (int i = 0; i < trainData.rows; i++) //{ // for (int j = 0; j < trainData.cols; j++) // cout << trainData.at<float>(i, j) << " "; // cout << endl; //} CvANN_MLP bp; CvANN_MLP_TrainParams param; param.term_crit = cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 10000, 0.001); // 设置终止条件: 迭代次数和误差阈值 param.train_method = CvANN_MLP_TrainParams::BACKPROP; //反向传播 BackProgation param.bp_dw_scale = 0.1; // 与反向传播方法相关的系数 param.bp_moment_scale = 0.1; // 与反向传播方法相关的系数 Mat layerSizes = (Mat_<int>(1, 4) << DIM, 8, 5, 1); // 设置网络层: 9->8->5->1 ,最终得到的是与标签该类的相似度(0-1之间) //create第二个参数可以设置每个神经节点的激活函数,默认为CvANN_MLP::SIGMOID_SYM,即Sigmoid函数 //同时提供的其他激活函数有Gauss(CvANN_mlp::GAUSSIAN)和阶跃函数(CvANN_MLP::IDENTITY)。 bp.create(layerSizes, CvANN_MLP::SIGMOID_SYM); //bp.create(laySizes, CvANN_MLP::GAUSSIAN); //bp.create(layerSizes, CvANN_MLP::IDENTITY); bp.train(trainData, trainLabel, Mat(), Mat(), param); bp.save("bp.xml"); //test float testData[COUNT_TEST][DIM] = { 0 }; ifstream in3("test_data.txt"); for (int i = 0; i < COUNT_TEST; i++) { for (int j = 0; j < DIM; j++) in3 >> testData[i][j]; } in3.close(); float testLabel[COUNT_TEST] = { 0 }; ifstream in4("test_label.txt"); for (int i = 0; i < COUNT_TEST; i++) in4 >> testLabel[i]; in4.close(); Mat testDataMat(COUNT_TEST, DIM, CV_32FC1, testData); Mat testLabelMat(COUNT_TEST, 1, CV_32FC1, testLabel); //for (int i = 0; i < testDataMat.rows; i++) //{ // for (int j = 0; j < testDataMat.cols; j++) // cout << testDataMat.at<float>(i, j) << " "; // cout << endl; //} int testResult[COUNT_TEST] = { 0 }; for (int i = 0; i < COUNT_TEST; i++) { Mat responseMat; //Mat sampleMat = (Mat_<float>(1, 9) << 4, 2, 1, 1, 2, 1, 2, 1, 1); //正确标签为0 //Mat sampleMat = (Mat_<float>(1, 9) << 7, 4, 6, 4, 6, 1, 4, 3, 1); //正确标签为1 float sz[DIM] = { 0 }; for (int j = 0; j < DIM;j++) sz[j] = testDataMat.at<float>(i, j); //for (int j = 0; j < DIM; j++) // cout << sz[j] << " "; //cout << endl; Mat sampleMat(1, DIM, CV_32FC1,sz); bp.predict(sampleMat, responseMat); float result = responseMat.at<float>(0,0); if (result > 0.5) testResult[i] = 1; else testResult[i] = 0; //cout << responseMat.rows << " " << responseMat.cols << endl; for (int i = 0; i < responseMat.rows; i++) { for (int j = 0; j < responseMat.cols; j++) cout << responseMat.at<float>(i, j) << " "; cout << endl; } } int CorrectionCount = 0; for (int i = 0; i < COUNT_TEST; i++) { if (testResult[i] == testLabel[i]) CorrectionCount++; } cout << "Correction = " << CorrectionCount << endl; return 0; } */
    转载请注明原文地址: https://ju.6miu.com/read-24680.html

    最新回复(0)