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:\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

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

 

        }

    }

}

  

运行结果

 

时间: 2024-11-10 00:25:54

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

编程-如何不使用Matlab已有命令编写BP神经网络基本原理,来实现手写数字识别?

问题描述 如何不使用Matlab已有命令编写BP神经网络基本原理,来实现手写数字识别? 如何不使用Matlab已有命令编写BP神经网络基本原理,来实现手写数字识别? 解决方案 http://download.csdn.net/detail/aoxiangyuntian123/8472775

下载的手写数字识别matlab源代码调试不出来,求助

问题描述 下载的手写数字识别matlab源代码调试不出来,求助 源链接 求详细调试方法 解决方案 至少把报错贴出来吧? 那个chargui 文件使用GUI编辑打开运行报错是什么?

labview+matlab-在Labview中调用Matlab程序时出错,错误提示Function函数无效

问题描述 在Labview中调用Matlab程序时出错,错误提示Function函数无效 请大神们帮帮忙,这个问题怎么解决啊? 解决方案 http://wenku.baidu.com/link?url=c_f-NBJBOaw_RveWarfinIctyj5GYUQlJagTkpE_eed4JkesENfgIO9JMUYs6uU9bW8onhml7JJ5eO2V80LcmS0GsnYdNwYGEzeUgACOguu

matlab-利用MTACOM在VC中调用MATLAB出错了

问题描述 利用MTACOM在VC中调用MATLAB出错了 错误如图,按照教程做的,哪里错了呢?请高手指教! 解决方案 http://wenku.baidu.com/link?url=fqKhUoFhm9j9Q8e2FEt26NU74u7Gfho1XNs0JYmGpOVMCuhzIg0cCwmB5r7nRadXRm-_wpPJP0wUIdaW3xC0dZyviNUyLEvCe73HnFABmQ7

OpenCV手写数字字符识别(基于k近邻算法)

  摘要 本程序主要参照论文,<基于OpenCV的脱机手写字符识别技术>实现了,对于手写阿拉伯数字的识别工作.识别工作分为三大步骤:预处理,特征提取,分类识别.预处理过程主要找到图像的ROI部分子图像并进行大小的归一化处理,特征提取将图像转化为特征向量,分类识别采用k-近邻分类方法进行分类处理,最后根据分类结果完成识别工作. 程序采用Microsoft Visual Studio 2010与OpenCV2.4.4在Windows 7-64位旗舰版系统下开发完成.并在Windows xp-32位

C#中调用MATLAB函数

问题描述 刚刚接触MATLAB和C#的混合编程,写好的MATLAB函数中的输入参数是一个矩阵和一个行向量,请问在C#中应该怎么表达MATLAB的矩阵和行向量? 解决方案 本帖最后由 qq_26570227 于 2016-05-14 09:34:46 编辑解决方案二:二维数组呀,可以用存数据解决方案三:http://blog.sina.com.cn/s/blog_62de7f7a01018qov.html

VB调用Matlab在WEDM仿真系统中的应用

基于BP神经网络的电火花线切割(WEDM)工艺仿真系统需要具有工艺数据库管理 .工艺效果预测.加工参数优化等设计功能.借助Matlab的神经网络工具箱,可 以建立良好的工艺效果预测模型和参数优化模型,这正是工艺仿真软件最主要的 功能要求.VB是Windows操作系统下优秀的可视化编程工具软件,在用户界面设计 和快速开发等方面具有独特的优势.同时,Matlab仿真软件以其强大的科学计算 功能和开放式开发思想使其成为当前最为流行的仿真计算工具.综合两种开发环 境各自的优势,可采用VB与Matlab混

机器学习算法汇总:人工神经网络、深度学习及其它

学习方式 根据数据类型的不同,对一个问题的建模有不同的方式.在机器学习或者人工智能领域,人们首先会考虑算法的学习方式.在机器学习领域,有几种主要的学习方式.将算法按照学习方式分类是一个不错的想法,这样可以让人们在建模和算法选择的时候考虑能根据输入数据来选择最合适的算法来获得最好的结果. 监督式学习: 在监督式学习下,输入数据被称为"训练数据",每组训练数据有一个明确的标识或结果,如对防垃圾邮件系统中"垃圾邮件""非垃圾邮件",对手写数字识别中的&

backp-用java写可以识别数字的BP神经网络

问题描述 用java写可以识别数字的BP神经网络 现在学校要求写一个可以识别数字的神经网络,要求最好用bp, 也可以用别的算法,语言可以任意,最好是java.数据事uci的optical recognition of handwritten digits 想知道有没有指导怎么一步一步建立的的教程,不知道如何建立这样的网络,代码里需要几层方法? 解决方案 参考:http://download.csdn.net/download/u012828028/6546885 解决方案二: BP神经网络应用于