zoukankan      html  css  js  c++  java
  • C#中调用Matlab人工神经网络算法实现手写数字识别

    • 手写数字识别实现

    设计技术参数:通过由数字构成的图像,自动实现几个不同数字的识别,设计识别方法,有较高的识别率

    关键字:二值化  投影  矩阵  目标定位  Matlab                                                              

    手写数字图像识别简介

    手写阿拉伯数字识别是图像内容识别中较为简单的一个应用领域,原因有被识别的模式数较少(只有0到9,10个阿拉伯数字)、阿拉伯数字笔画少并且简单等。手写阿拉伯数字的识别采用的方法相对于人脸识别、汉字识别等应用领域来说可以采用更为灵活的方法,例如基于规则的方法、基于有限状态自动机的方法、基于统计的方法和基于神经网络的方法等。本文的开始部分先对手写阿拉伯数字识别的整个处理流程进行论述,而这个流程也可以用于图像中其他模式的识别。当然这个处理流程也不是唯一的,可以根据不同的模式识别应用场景进行与之不同的预处理流程。

    手写数字图像识别的主要流程

    第一步:对源图像进行黑白二值化处理;0数字的二值化(左)和1的二值化处理(右)

    第二步:将图像在水平方向上和竖直方向上进行投影,这样通过投影图形就可以区分1和0的特征;

    第三步:用投影计算出区域的横纵坐标,将其分为九份。定位出数字所在图像中的位置,提取该部分进行分析。

    第四步:数字0和1的特征比较与识别

    在0和一的比较中发现,在分成的九个区域的中间区域,0中间区域灰度为0,1中间区域灰度为1。

    • 人工神经网络

    人类之所以能够思考,学习,判断,大部分都要归功于人脑中复杂的神经网络。虽然现在人脑的机理还没有完全破译,但是人脑中神经元之间的连接,信息的传递都已为人所知晓。于是人们就想能否模拟人脑的功能用于解决其他问题,这就发展出人工神经网络。
    人工神经网络(artificial neural network,缩写ANN),是一种模仿生物神经网络的结构和功能的数学模型或计算模型。神经网络由大量的人工神经元联结进行计算。大多数情况下人工神经网络能在外界信息的基础上改变内部结构,是一种自适应系统。现代神经网络是一种非线性统计性数据建模工具,常用来对输入和输出间复杂的关系进行建模,或用来探索数据的模式。
    神经网络是一种运算模型,由大量的节点(或称“神经元”,或“单元”)和之间相互联接构成。每个节点代表一种特定的输出函数,称为激励函数(activation function)。每两个节点间的连接都代表一个对于通过该连接信号的加权值,称之为权重(weight),这相当于人工神经网络的记忆。网络的输出则依网络的连接方式,权重值和激励函数的不同而不同。而网络自身通常都是对自然界某种算法或者函数的逼近,也可能是对一种逻辑策略的表达。

    • samples
    • 识别流程

    流程如图,首先要对数据进行处理,这个主要是批量读取图片和特征提取的过程,特征提取的方法很多,这里只挑选最简单的来实现,然后是训练出一个神经网络的模型,最后用测试数据进行测试。为了方便,这里的神经网络的创建,训练和测试采用Matlab函数来实现。

    • 构造标签

    要构造出适合神经网络的标签,在这个例子中有10个类,若为某个标签,那么这个位置的值为1,其余为0。

    • Matlab实现代码

    数字特征提取部分

    featureextract.m

    % featureextract  数字特征提取部分

    clear;

    clc;

    % global定义全局变量P T,by:chen

    global P T;

     

    I = imread('0.bmp');

    读入数字图片,为个人用画图板制作的图片

    p(1,:)=inputvar(I);

    % inputvar(x)函数为特征提取函数,对第一个0样本的图片进行特征提取

     

    %I = imread('00.bmp');

    I = imread('cccc0.bmp');

    p(2,:)=inputvar(I);

    读入第二个关于字符0的样本

     

    I = imread('000.bmp');

    p(3,:)=inputvar(I);

     

    I = imread('0000.bmp');

    p(4,:)=inputvar(I);

     

    I = imread('1.bmp');

    p(5,:)=inputvar(I);

     

    %I = imread('11.bmp');

    I = imread('cc15.bmp');

    p(6,:)=inputvar(I);

     

    I = imread('111.bmp');

    p(7,:)=inputvar(I);

     

    I = imread('1111.bmp');

    p(8,:)=inputvar(I);

     

    I = imread('2.bmp');

    p(9,:)=inputvar(I);

     

    I = imread('22.bmp');

    p(10,:)=inputvar(I);

     

    %I = imread('222.bmp');

    I = imread('cccc2.bmp');

    p(11,:)=inputvar(I);

     

    I = imread('2222.bmp');

    p(12,:)=inputvar(I);

     

    %I = imread('3.bmp');

    I = imread('cccc3.bmp');

    p(13,:)=inputvar(I);

     

    I = imread('33.bmp');

    p(14,:)=inputvar(I);

     

    I = imread('333.bmp');

    p(15,:)=inputvar(I);

     

    I = imread('3333.bmp');

    p(16,:)=inputvar(I);

     

    I = imread('4.bmp');

    %I = imread('cc444.bmp');

    p(17,:)=inputvar(I);

     

    I = imread('44.bmp');

    p(18,:)=inputvar(I);

     

    I = imread('444.bmp');

    p(19,:)=inputvar(I);

     

    %I = imread('4444.bmp');

    I = imread('cc444.bmp');

    p(20,:)=inputvar(I);

     

    %I = imread('5.bmp');

    I = imread('cccc5.bmp');

    p(21,:)=inputvar(I);

     

    I = imread('55.bmp');

    p(22,:)=inputvar(I);

     

    I = imread('555.bmp');

    p(23,:)=inputvar(I);

     

    I = imread('5555.bmp');

    p(24,:)=inputvar(I);

     

    I = imread('6.bmp');

    p(25,:)=inputvar(I);

     

    I = imread('66.bmp');

    p(26,:)=inputvar(I);

     

    I = imread('666.bmp');

    p(27,:)=inputvar(I);

     

    I = imread('6666.bmp');

    p(28,:)=inputvar(I);

     

    I = imread('7.bmp');

    p(29,:)=inputvar(I);

     

    I = imread('77.bmp');

    p(30,:)=inputvar(I);

     

    I = imread('777.bmp');

    p(31,:)=inputvar(I);

     

    I = imread('7777.bmp');

    p(32,:)=inputvar(I);

     

    I = imread('8.bmp');

    p(33,:)=inputvar(I);

     

    I = imread('88.bmp');

    p(34,:)=inputvar(I);

     

    I = imread('888.bmp');

    p(35,:)=inputvar(I);

     

    I = imread('8888.bmp');

    p(36,:)=inputvar(I);

     

    I = imread('9.bmp');

    p(37,:)=inputvar(I);

     

    I = imread('99.bmp');

    p(38,:)=inputvar(I);

     

    I = imread('999.bmp');

    p(39,:)=inputvar(I);

     

    I = imread('9999.bmp');

    p(40,:)=inputvar(I);

     

    I = imread('test0.bmp');

    p(41,:)=inputvar(I);

     

    I = imread('test00.bmp');

    p(42,:)=inputvar(I);

     

    I = imread('test1.bmp');

    p(43,:)=inputvar(I);

     

    I = imread('test11.bmp');

    p(44,:)=inputvar(I);

     

    I = imread('test2.bmp');

    p(45,:)=inputvar(I);

     

    I = imread('test22.bmp');

    p(46,:)=inputvar(I);

     

    I = imread('test3.bmp');

    p(47,:)=inputvar(I);

     

    I = imread('test33.bmp');

    p(48,:)=inputvar(I);

     

    I = imread('test4.bmp');

    p(49,:)=inputvar(I);

     

    I = imread('test44.bmp');

    p(50,:)=inputvar(I);

     

    I = imread('test5.bmp');

    p(51,:)=inputvar(I);

     

    I = imread('test55.bmp');

    p(52,:)=inputvar(I);

     

    I = imread('test6.bmp');

    p(53,:)=inputvar(I);

     

    I = imread('test7.bmp');

    p(54,:)=inputvar(I);

     

    I = imread('test8.bmp');

    p(55,:)=inputvar(I);

     

    I = imread('test9.bmp');

    p(56,:)=inputvar(I);

     

    P = p;

    输入的训练与测试样本集

    T = [0 0 0 0;

        0 0 0 0;

        0 0 0 0;

        0 0 0 0;

        0 0 0 1;

        0 0 0 1;

        0 0 0 1;

        0 0 0 1;

        0 0 1 0;

        0 0 1 0;

        0 0 1 0;

        0 0 1 0;

        0 0 1 1;

        0 0 1 1;

        0 0 1 1;

        0 0 1 1;

        0 1 0 0;

        0 1 0 0;

        0 1 0 0;

        0 1 0 0;

        0 1 0 1;

        0 1 0 1;

        0 1 0 1;

        0 1 0 1;

        0 1 1 0;

        0 1 1 0;

        0 1 1 0;

        0 1 1 0;

        0 1 1 1;

        0 1 1 1;

        0 1 1 1;

        0 1 1 1;

        1 0 0 0;

        1 0 0 0;

        1 0 0 0;

        1 0 0 0;

        1 0 0 1;

        1 0 0 1;

        1 0 0 1;

        1 0 0 1

        0 0 0 0

        0 0 0 0

        0 0 0 1

        0 0 0 1

        0 0 1 0

        0 0 1 0

        0 0 1 1

        0 0 1 1

        0 1 0 0

        0 1 0 0

        0 1 0 1

        0 1 0 1

        0 1 1 0

        0 1 1 1

        1 0 0 0

        1 0 0 1];

    输出的训练与测试样本

    ttest = [0 0 0 0   

        0 0 0 1   

        0 0 1 0   

        0 0 1 1   

        0 1 0 0   

        0 1 0 1

        0 1 1 0

        0 1 1 1

        1 0 0 0

        1 0 0 1];

    % 1至9数字的标准输出

     

    P = P';

    T = T';

    ttest = ttest';

    save featureextractPTttest

    保存特征提取后的输入输出样本数据,生成mat文件以便训练与测试时对样本数据的调用

     

    特征提取

    % inputvar   特征提取

    function y=inputvar(I)

    % inputvar   特征提取

    b = find(I>130);%I:读入的待辨认的数字图片,find(I>130):找出I中大于130的坐标,返回的是线性索引

    I(b) = 1;%将图像中大于130的地方置1

     对数字图片进行二值化处理,读入的图片形式简单以致于二值化方法简单

    图像预处理部分

     

    [m,n] = size(I);%获取图片的尺寸,m=16,n=8

    p = zeros(1,17);%产生一个1*17的零向量

    for k=1:4

        for i=1+(k-1)*4:m/4+(k-1)*4

            for j=1:n/2

                if I(i,j)==0

                    p(k) = p(k)+1;

                else

                    p(k) = p(k);

                end

            end

            for j=n/2+1:n

                if I(i,j)==0

                    p(k+4) = p(k+4)+1;

                else

                    p(k+4) = p(k+4);

                end

            end

        end

    end

     把图片分成八个独立区域计算各自的图象密度,作为部分特征向量

    p(9) = p(1)+p(2);

    p(10) = p(3)+p(4);

    p(11) = p(5)+p(6);

    p(12) = p(7)+p(8);

    p(13) = p(1)+p(5);

    p(14) = p(2)+p(6);

    p(15) = p(3)+p(7);

    p(16) = p(4)+p(8);

    p(17) = p(9)+p(10)+p(11)+p(12);

    y = p/128;

     合并区域的图像密度作为其他部分特征向量

     

    网络训练与仿真部分

    网络训练与仿真部分

    % bpnntrain  网络训练与仿真部分

    clear

    clc

     

    %load featureextract;

    load('D:featureextract');

    调用输入输出样本数据

    P_train = P(:,1:40);

    %P_train:训练样本集合

    T_train = T(:,1:40);

    P_test = P(:,40:56);

    T_test = T(:,40:56);

     

    echo on

    net=newff(minmax(P_train),[9 4],{'tansig','tansig','tansig'},'trainlm');

    %newff:建立一个BP网络

    %minmax(P_train):对神经网络输入的最大最小值的限制

    %[9 4]:神经网络的层结构

    %{'tansig','tansig','tansig'}:神经网络各层转移函数

    %'trainlm':训练函数

    利用工具箱建立前向BP网络,输入输出隐层的传递函数均为S型的正切函数,使用Levenberg-Marquard算法进行训练

    隐层设置9个神经元,4个神经元输出

    net = init(net);

    网络初始化

    [m1,n1]=size(net.IW{1,1});

    net.IW{1,1}=0.3*ones(m1,n1);

    初始化当前输入层权值

    [m2,n2]=size(net.LW{2,1});

    net.LW{2,1}=0.3*ones(m2,n2);

    初始化隐层与输出层的连接权值

    net.trainParam.show=100; %显示的间隔次数

    net.trainParam.lr=0.01; %网络学习速率

    net.trainParam.mc=0.9; %动量因子

    net.trainParam.epochs=1000; %最大训练次数

    net.trainParam.goal=0.001;%性能目标值

    设置训练参数

    [net,tr] = train(net,P_train,T_train);

    静态批处理方式进行网络训练,net:更新了权值的神经网络,tr:训练次数和每次训练的误差

    fig = plotperf(tr)

     

    Y = sim(net,P_train);

    对训练后的网络进行仿真

    E = T_train-Y;

    perf=mse(E)

    计算仿真误差

    echo off

     

    save bpnntrainnetfig

     

     

     

     

     

     

    网络测试与检测部分

    % nnceshi   网络测试与检测部分

    function result = TestDigit( img )

    %UNTITLED Summary of this function goes here

    %   Detailed explanation goes here

     

    % global定义全局变量P T,by:chen

    global P T;

    数字特征提取

    %load featureextract;

    load('D:featureextract');

     

    网络训练与仿真部分

    %load bpnntrain net;

    load('D:pnntrain');

     

    % P_test:测试样本的特征向量

    P_test = P(:,40:56);

    T_test = T(:,40:56);

     

    对训练后的网络进行测试,net:训练完成了的网络,P_test:测试样本的特征向量,Y:神经网络的输出

    仿真

    Y = sim(net,P_test);

     

    E = T_test-Y;

     

    计算测试误差,暂时注释掉====== by:chenqp

    %perf=mse(E)

    perf=mse(E);

    读入待辨认的数字图片,检测网络

    I = imread(img);

    调用特征提取函数提取数据特征

    ptest = inputvar(I);

     

    ptest = ptest';

    Y = sim(net,ptest);

    D = round(Y);%对Y取整

    Num = 8*D(1,1)+4*D(2,1)+2*D(3,1)+D(4,1);

    暂时注释掉ttest======= by:chenqp

    % ttest = ttest(:,Num+1)

    ttest = ttest(:,Num+1);

    E = ttest-abs(Y);

    %均方误差

    perf=mse(E);

    result = Num;

     

    end

     

     

    封装成C#可以调用的DLL

    C#调用代码实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    using System;
    using System.Collections.Generic;
    using QpSolution;
    using MathWorks.MATLAB.NET.Arrays;
    using MathWorks.MATLAB.NET.Utility;
     
     
    namespace TestMatlab
    {
        class Program
        {
            static void Main(string[] args)
            {
                // 直接使用Math.Pow计算x的y次方
                List<double> x = new List<double>();
                List<double> y = new List<double>();
                List<double> z1 = new List<double>();
                List<double> z2 = new List<double>();
                Random random = new Random();
     
                for (int i = 0; i < 1000000; i++)
                {
                    x.Add(random.Next(1000) * random.NextDouble());
                    y.Add(random.Next(1000) * random.NextDouble());
                }
                DateTime a = DateTime.Now;
                for (int i = 0; i < x.Count; i++)
                {
                    z1.Add(Math.Pow(x[i], y[i]));
                }
                DateTime b = DateTime.Now;
                // 直接使用Math.Pow计算x的y次方,第一次运算花费时间ms
                Console.WriteLine((b - a).TotalMilliseconds);
     
                a = DateTime.Now;
                for (int i = 0; i < x.Count; i++)
                {
                    z2.Add(Math.Pow(x[i], y[i]));
                }
                b = DateTime.Now;
                // 直接使用Math.Pow计算x的y次方,第二次运算花费时间ms
                Console.WriteLine((b - a).TotalMilliseconds);
     
                a = DateTime.Now;
                TestClass tc1 = new TestClass();
                var z3 = tc1.TestFun((MWNumericArray)x.ToArray(), (MWNumericArray)y.ToArray()).ToArray();
                b = DateTime.Now;
                Console.WriteLine((b - a).TotalMilliseconds);
     
                a = DateTime.Now;
                TestClass tc2 = new TestClass();
                var z4 = tc2.TestFun((MWNumericArray)x.ToArray(), (MWNumericArray)y.ToArray()).ToArray();
                b = DateTime.Now;
                Console.WriteLine((b - a).TotalMilliseconds);
     
     
                // MWArray是数据类型的一个父类,下面包括了很多数据类
                MWNumericArray mw1 = new MWNumericArray(MWArrayComplexity.Real, 1);
                mw1[1] = 2;
                MWNumericArray mw2 = new MWNumericArray(MWArrayComplexity.Real, 1);
                mw2[1] = 3;
                var z5 = tc1.TestFun(mw1, mw2);
                Console.WriteLine(z5);  // 8
     
                // 传入字符串
                MWCharArray str = "D:\test7.bmp";
                var z6 = tc1.TestChar(str);
                Console.WriteLine(z6);
     
                // 测试传入的文件是否存在,并拿到Matlab返回值
                MWCharArray file = "D:\test7.bmp";
                var z7 = tc1.TestFileExist(file);
                Console.WriteLine(z7);
     
                // 测试人工神经网络识别手写数字,返回matlab函数识别结果
                MWCharArray img1 = "D:\testPic\c2.bmp";
                Console.WriteLine("开始识别第1个图片....");
                var pic1 = tc1.TestDigit(img1);
                Console.WriteLine("第1个图片识别结果为:" + pic1);
     
                MWCharArray img2 = "D:\testPic\cccc0.bmp";
                Console.WriteLine("开始识别第2个图片....");
                var pic2 = tc1.TestDigit(img2);
                Console.WriteLine("第2个图片识别结果为:" + pic2);
     
                MWCharArray img3 = "D:\testPic\cccc2.bmp";
                Console.WriteLine("开始识别第3个图片....");
                var pic3 = tc1.TestDigit(img3);
                 Console.WriteLine("第3个图片识别结果为:" + pic3);
     
                MWCharArray img4 = "D:\testPic\cccc3.bmp";
                Console.WriteLine("开始识别第4个图片....");
                var pic4 = tc1.TestDigit(img4);
                Console.WriteLine("第4个图片识别结果为:" + pic4);
     
                MWCharArray img5 = "D:\testPic\cccc5.bmp";
                Console.WriteLine("开始识别第5个图片....");
                var pic5 = tc1.TestDigit(img5);
                Console.WriteLine("第5个图片识别结果为:" + pic5);
     
                MWCharArray img6 = "D:\testPic\abc7.bmp";
                Console.WriteLine("开始识别第6个图片....");
                var pic6 = tc1.TestDigit(img6);
                Console.WriteLine("第6个图片识别结果为:" + pic6);
     
                MWCharArray img7 = "D:\testPic\abc8.bmp";
                Console.WriteLine("开始识别第7个图片....");
                var pic7 = tc1.TestDigit(img7);
                Console.WriteLine("第7个图片识别结果为:" + pic7);
     
                Console.Read();
     
            }
        }
    }

      

    运行结果

     

  • 相关阅读:
    订阅发布模式概念基础
    HTML与CSS之display:none
    HTML与CSS之导航栏
    微信小程序-笔记
    基于设计模式的用户管理
    微信小程序-开发组件-笔记1
    JavaScript异常处理
    微信小程序开发-笔记
    封装类实现增删改查
    脚本方式实现数据库增删改查
  • 原文地址:https://www.cnblogs.com/waw/p/5521960.html
Copyright © 2011-2022 走看看