Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / 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:chenglobal 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=8p = 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    endend % 把图片分成八个独立区域计算各自的图象密度,作为部分特征向量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 onnet=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:chenglobal 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#调用代码实现

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();
 
        }
    }
}

运行结果

本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-04/130564.htm