当前位置:   article > 正文

C#中调用Matlab人工神经网络算法实现手写数字识别

c# 识别图片中的手写数字
  • 手写数字识别实现

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

关键字:二值化  投影  矩阵  目标定位  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];

% 19数字的标准输出

 

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:\bpnntrain');

 

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

  

运行结果

 

转载于:https://www.cnblogs.com/Bobby0322/p/5362763.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/347139
推荐阅读
相关标签
  

闽ICP备14008679号