人工神经网络(ANN) 简称神经网络(NN),能模拟生物神经系统对物体所作出的交互反应,是由具有适应性简单单元(称为神经元)组成的广泛并行互连网络

1  神经元

1.1  M-P 神经元

如下图所示,来自其它神经元的信号,$x_1, x_2, ... , x_n $,传递过来作为输入信号,并通过带权重 ($w_1, w_2, ... , w_n$) 的连接 (connection) 继续传递,

然后神经元的总输入值 $\sum w_i x_i$ 与阈值 $\theta$ 作比较,最后经过激活函数$\,f\,$产生神经元的输出: $y = f\left(\,\sum \limits_{i=1}^n {w_i x_i} - \theta \right)$

1.2  激活函数 (activation function)

理想中,阶跃函数可作为激活函数,将输入值映射为输出值 “0” 和 “1;实际中,常用 Sigmoid 函数作激活函数, $f(x)=\,\dfrac{1}{1+e^{-x}}$,如下图所示:

OpenCV 中使用的激活函数是另一种形式,$f(x)=\beta \,\dfrac{1-e^{-\alpha x}}{1+e^{-\alpha x}}$

当 α = β = 1 时,$f(x)=\dfrac{1-e^{-x}}{1+e^{x}}$,该函数把可能在较大范围内变化的输入值,“挤压” 到 (-1, 1) 的输出范围内

具体的设置函数如下,param1 --> α,param2 --> β

  1. // 设置激活函数,目前只支持 ANN_MLP::SIGMOID_SYM
  2. virtual void cv::ml::ANN_MLP::setActivationFunction(int type, double param1 = , double param2 = );

2  神经网络

2.1  感知机 (perceptron)

  感知机由两层神经元组成,输入层接收外界输入信号,而输出层则是一个 M-P 神经元。

实际上,感知机可视为一个最简单的“神经网络”,用它可很容易的实现逻辑与、或、非等简单运算。

2.2 层级结构

常见的神经网络,可分为三层:输入层、隐含层、输出层。输入层接收外界输入,隐层和输出层负责对信号进行加工,输出层输出最终的结果。

以下图为例:每层神经元与下一层神经元全互连,而同层神经元之间不连接,也不存在跨层连接,这样的结构称为“多层前馈神经网络”(multi-layer feedforward neural networks)

2.3  层数设置

OpenCV 中,设置神经网络层数和神经元个数的函数为 setLayerSizes(InputArray _layer_sizes),则上图对应的 InputArray 可由如下代码来构成

  1. // (a) 3层,输入层神经元个数为 4,隐层的为 6,输出层的为 4
  2. Mat layers_size = (Mat_<int>(,) << ,,);
  3.  
  4. // (b) 4层,输入层神经元个数为 4,第一个隐层的为 6,第二个隐层的为 5,输出层的为 4
  5. Mat layers_size = (Mat_<int>(,) << ,,5,);

如何设置隐层神经元的个数仍是个未决的问题,实际中多采用“试错法”来调整

3  OpenCV 函数

1)  创建

  1. static Ptr<ANN_MLP> cv::ml::ANN_MLP::create(); // 创建空模型

2) 设置参数

  1. // 设置神经网络的层数和神经元数量
  2. virtual void cv::ml::ANN_MLP::setLayerSizes(InputArray _layer_sizes);
  3.  
  4. // 设置激活函数,目前只支持 ANN_MLP::SIGMOID_SYM
  5. virtual void cv::ml::ANN_MLP::setActivationFunction(int type, double param1 = , double param2 = );
  6.  
  7. // 设置训练方法,默认为 ANN_MLP::RPROP,较常用的是 ANN_MLP::BACKPROP
  8. // 若设为 ANN_MLP::BACKPROP,则 param1 对应 setBackpropWeightScale()中的参数,param2 对应 setBackpropMomentumScale() 中的参数
  9. virtual void cv::ml::ANN_MLP::setTrainMethod(int method, double param1 = , double param2 = );
  10. virtual void cv::ml::ANN_MLP::setBackpropWeightScale(double val); // 默认值为 0.1
  11. virtual void cv::ml::ANN_MLP::setBackpropMomentumScale(double val); // 默认值为 0.1
  12.  
  13. // 设置迭代终止准则,默认为 TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 1000, 0.01)
  14. virtual void cv::ml::ANN_MLP::setTermCriteria(TermCriteria val);

3)  训练

  1. // samples - 训练样本; layout - 训练样本为 “行样本” ROW_SAMPLE 或 “列样本” COL_SAMPLE; response - 对应样本数据的分类结果
    virtual bool cv::ml::StatModel::train(InputArray samples,int layout,InputArray responses);

4)  预测

  1. // samples,输入的样本书数据;results,输出矩阵,默认不输出;flags,标识,默认为 0
    virtual float cv::ml::StatModel::predict(InputArray samples, OutputArray results=noArray(),int flags=) const;      

4 代码示例

  下面是 OpenCV 3.3 中,在“支持向量机”的例程上做的修改,使用 BP 神经网络,实现了和 SVM 相同的分类功能。

OpenCV 中的 支持向量机 (Support Vector Machine),可参见另一篇博文 OpenCV 之 支持向量机 (一)

  1. #include "opencv2/core/core.hpp"
  2. #include "opencv2/imgproc/imgproc.hpp"
  3. #include "opencv2/imgcodecs/imgcodecs.hpp"
  4. #include "opencv2/highgui/highgui.hpp"
  5. #include "opencv2/ml/ml.hpp"
  6.  
  7. using namespace cv;
  8.  
  9. int main()
  10. {
  11. // 512 x 512 零矩阵
  12. int width = , height = ;
  13. Mat img = Mat::zeros(height, width, CV_8UC3);
  14.  
  15. // 训练样本
  16. float train_data[][] = { { , },{ , },{ , },{ , },{, },{, } };
  17. float labels[] = {,,,,,}; // 每个样本数据对应的输出
  18. Mat train_data_mat(, , CV_32FC1, train_data);
  19. Mat labels_mat(, , CV_32FC1, labels);
  20.  
  21. // BP 模型创建和参数设置
  22. Ptr<ml::ANN_MLP> bp = ml::ANN_MLP::create();
  23.  
  24. Mat layers_size = (Mat_<int>(,) << ,,); // 2维点,1维输出
  25. bp->setLayerSizes(layers_size);
  26.  
  27. bp->setTrainMethod(ml::ANN_MLP::BACKPROP,0.1,0.1);
  28. bp->setActivationFunction(ml::ANN_MLP::SIGMOID_SYM);
  29. bp->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, , /*FLT_EPSILON*/1e-));
  30.  
  31. // 保存训练好的神经网络参数
  32. bool trained = bp->train(train_data_mat,ml::ROW_SAMPLE,labels_mat);
  33. if (trained) {
  34. bp->save("bp_param");
  35. }
  36.  
  37. // 创建训练好的神经网络
  38. // Ptr<ml::ANN_MLP> bp = ml::ANN_MLP::load("bp_param");
  39.  
  40. // 显示分类的结果
  41. Vec3b green(, , ), blue(, , );
  42. for (auto i=; i<img.rows; ++i) {
  43. for (auto j=; j<img.cols; ++j) {
  44. Mat sample_mat = (Mat_<float>(, ) << j, i);
  45. Mat response_mat;
  46. bp->predict(sample_mat,response_mat);
  47. float response = response_mat.ptr<float>()[];
  48. if (response > 0.5) {
  49. img.at<Vec3b>(i, j) = green;
  50. } else if (response < 0.5) {
  51. img.at<Vec3b>(i, j) = blue;
  52. }
  53. }
  54. }
  55.  
  56. // 画出训练样本数据
  57. int thickness = -;
  58. int lineType = ;
  59. circle(img, Point(, ), , Scalar(, , ), thickness, lineType);
  60. circle(img, Point(, ), , Scalar(, , ), thickness, lineType);
  61. circle(img, Point(, ), , Scalar(, , ), thickness, lineType);
  62. circle(img, Point(, ), , Scalar(, , ), thickness, lineType);
  63. circle(img, Point(, ), , Scalar(, , ), thickness, lineType);
  64. circle(img, Point(, ), , Scalar(, , ), thickness, lineType);
  65.  
  66. imwrite("result.png", img); // 保存训练的结果
  67. imshow("BP Simple Example", img);
  68.  
  69. waitKey();
  70. }

运行结果如下所示:

注意:OpenCV 3.0 以上版本,相较之前的版本,其中有关机器学习的部分做了较大改动,本人也是踩了一些坑才得到预期的效果。

1)  代码 #25,必须在 setActivationFunction() 之前,否则训练后的结果多为 nan

2)  代码 #46,response_mat 为预测的结果。若输出向量为 1 列,则如 #47 所示,可直接取出预测结果;若输出向量为 n 列,则可取平均值或者最大值。

同时,根据平均值或最大值,代码 #48 处的阈值也要相应的改变。

  1. float response = ;
  2. for (auto i=;i<n;++i) {
  3. response += response_mat.ptr<float>()[i];
  4. }

3)  代码 #39,若已经训练好神经网络的参数,并将其保存到文件 bp_param 中。

则可将 #22 ~ #35 全部注释掉,再反注释掉 #38,这样,直接加载训练好的神经网络,便可以使用了。

参考资料

<机器学习> 周志华  第5章

<统计学习方法> 李航  第1章

OpenCV 3.0  Tutorials  -- Neural Networks

OpenCV进阶之路:神经网络识别车牌字符      ☆Ronny丶

【模式识别】OpenCV中使用神经网络 CvANN_MLP      xiaowei_cqu

OpenCV 之 神经网络 (一)的更多相关文章

  1. opencv BP神经网络使用过程

       1.OpenCV中的神经网络 OpenCV中封装了类CvANN_MLP,因而神经网络利用很方便.   首先构建一个网络模型:     CvANN_MLP ann;     Mat structu ...

  2. OpenCV——ANN神经网络

    ANN-- Artificial Neural Networks 人工神经网络 //定义人工神经网络 CvANN_MLP bp; // Set up BPNetwork's parameters Cv ...

  3. OpenCV进阶之路:神经网络识别车牌字符

    1. 关于OpenCV进阶之路 前段时间写过一些关于OpenCV基础知识方面的系列文章,主要内容是面向OpenCV初学者,介绍OpenCV中一些常用的函数的接口和调用方法,相关的内容在OpenCV的手 ...

  4. 使用HOG特征+BP神经网络进行车标识别

    先挖个坑,快期末考试了,有空填上w 好了,今晚刚好有点闲,就把坑填上吧. //-------------------------------开篇---------------------------- ...

  5. Python实现一个简单的微信跳一跳辅助

    1.  前言 微信的跳一跳相信大家都很熟悉了,而且现在各种外挂.辅助也是满天飞,反正本人的好友排行榜中已经是八九百都不足为奇了.某宝上一搜一堆结果,最低的居然只要3块多,想刷多少分就刷多少分,真是离谱 ...

  6. multi-layer perceptrons, MLP)模型,CvANN_MLP。

    #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <ope ...

  7. ApacheCN 计算机视觉译文集 20211110 更新

    OpenCV3 和 Qt5 计算机视觉 零.前言 一.OpenCV 和 Qt 简介 二.创建我们的第一个 Qt 和 OpenCV 项目 三.创建一个全面的 Qt + OpenCV 项目 四.Mat和Q ...

  8. ApacheCN 计算机视觉译文集 20210212 更新

    新增了六个教程: OpenCV 图像处理学习手册 零.前言 一.处理图像和视频文件 二.建立图像处理工具 三.校正和增强图像 四.处理色彩 五.视频图像处理 六.计算摄影 七.加速图像处理 Pytho ...

  9. 【转】OpenCV中使用神经网络 CvANN_MLP

    原文见:http://blog.csdn.net/xiaowei_cqu/article/details/9027617 OpenCV的ml模块实现了人工神经网络(Artificial Neural ...

随机推荐

  1. JavaScript知识点整理 (二)

    1)函数概述 1.函数是一块 JS 代码,被定义一次,但可以执行和调用多次. JS 中的函数也是对象,所以 JS 函数可以像其它对象那样操作和传递,所以也常叫 JS 中的函数为函数对象. 2.函数也是 ...

  2. Java IO和NIO文章目录

    1.java IO详尽解析 2.深入分析 Java I/O 的工作机制 3.InputStream类详解 4.OutputStream类详解 5.JAVA的节点流和处理流 6.FileInputStr ...

  3. 受够了if (ModelState.IsValid)?ActionFitlter也是一路的坑啊!

    这篇博客真是干货,干得估计还有点“磕牙”,所以还提供视频和代码.但基础稍弱的同学,怕还是得自行补充一些基础知识——就一篇文章,确实没办法面面俱到. 视频和代码下载:Demo - 百度云盘 · 一起帮 ...

  4. 【JAVAWEB学习笔记】18_el&jstl&javaee的开发模式

    一.EL技术 1.EL 表达式概述 EL(Express Lanuage)表达式可以嵌入在jsp页面内部,减少jsp脚本的编写,EL 出现的目的是要替代jsp页面中脚本的编写. 2.EL从域中取出数据 ...

  5. jQ实现的一个轮播图

    众所周知,轮播图是被广泛的运用的. 轮播图我们在很多的网站上都可以看到,例如淘宝.京东这些网站都很常见. 下面开始我们的轮播之旅: 搭建我们的骨架: <!DOCTYPE html> < ...

  6. Word Ladder II 2015年6月4日

    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...

  7. ES6核心内容精讲--快速实践ES6(一)

    前言 本文大量参考了阮一峰老师的开源教程ECMAScript6入门,适合新手入门或者对ES6常用知识点进行全面回顾,目标是以较少的篇幅涵盖ES6及部分ES7在实践中的绝大多数使用场景.更全面.更深入的 ...

  8. java集合(2)- java中HashMap详解

    java中HashMap详解 基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了非同步和允许使用 null 之外,HashMap 类与 H ...

  9. Java 9 揭秘(1.Java入门介绍)

    文 by / 林本托 在第一部分中,主要讲解如下内容: JDK 9 包含了哪些内容 运行代码的系统要求 如何安装 NetBeans 1 JDK 介绍 JDK 9是Java开发工具包的第九个主要版本,计 ...

  10. Java之JSON数据

    特别注意:使用JSON前需要导包 操作步骤地址:http://blog.csdn.net/baidu_37107022/article/details/70876993 1.定义 JSON(JavaS ...