• 手写数字识别实现

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

关键字:二值化  投影  矩阵  目标定位  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#调用代码实现

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

  

运行结果

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

  1. 基于OpenCV的KNN算法实现手写数字识别

    基于OpenCV的KNN算法实现手写数字识别 一.数据预处理 # 导入所需模块 import cv2 import numpy as np import matplotlib.pyplot as pl ...

  2. 使用AI算法进行手写数字识别

    人工智能   人工智能(Artificial Intelligence,简称AI)一词最初是在1956年Dartmouth学会上提出的,从那以后,研究者们发展了众多理论和原理,人工智能的概念也随之扩展 ...

  3. 学习笔记CB009:人工神经网络模型、手写数字识别、多层卷积网络、词向量、word2vec

    人工神经网络,借鉴生物神经网络工作原理数学模型. 由n个输入特征得出与输入特征几乎相同的n个结果,训练隐藏层得到意想不到信息.信息检索领域,模型训练合理排序模型,输入特征,文档质量.文档点击历史.文档 ...

  4. Pytorch1.0入门实战一:LeNet神经网络实现 MNIST手写数字识别

    记得第一次接触手写数字识别数据集还在学习TensorFlow,各种sess.run(),头都绕晕了.自从接触pytorch以来,一直想写点什么.曾经在2017年5月,Andrej Karpathy发表 ...

  5. 【TensorFlow-windows】(四) CNN(卷积神经网络)进行手写数字识别(mnist)

    主要内容: 1.基于CNN的mnist手写数字识别(详细代码注释) 2.该实现中的函数总结 平台: 1.windows 10 64位 2.Anaconda3-4.2.0-Windows-x86_64. ...

  6. KNN分类算法实现手写数字识别

    需求: 利用一个手写数字“先验数据”集,使用knn算法来实现对手写数字的自动识别: 先验数据(训练数据)集: ♦数据维度比较大,样本数比较多. ♦ 数据集包括数字0-9的手写体. ♦每个数字大约有20 ...

  7. CNN:人工智能之神经网络算法进阶优化,六种不同优化算法实现手写数字识别逐步提高,应用案例自动驾驶之捕捉并识别周围车牌号—Jason niu

    import mnist_loader from network3 import Network from network3 import ConvPoolLayer, FullyConnectedL ...

  8. 实验楼 1. k-近邻算法实现手写数字识别系统--《机器学习实战 》

    首先看看一些关键词:K-NN算法,训练集,测试集,特征(空间),标签 举实验楼中的样例,通俗的讲讲K-NN算法:电影有两个分类(标签)-动作片-爱情片.两个特征--打斗场面--亲吻画面. 将那些数字和 ...

  9. KNN算法案例--手写数字识别

    import numpy as np import matplotlib .pyplot as plt import pandas as pd from sklearn.neighbors impor ...

随机推荐

  1. str_replace() 用法bug和技巧

    语法 str_replace(find,replace,string,count) 参数 描述 find 必需.规定要查找的值. replace 必需.规定替换 find 中的值的值. string ...

  2. easyUI datagrid笔记

    easyUI datagrid 简单使用与注意细节 背景: 业余爱好,使用了一下easyUI的搜索框与数据表格,并把两者整合起来进行使用. 使用前提(引入需要的js and css): <lin ...

  3. 浏览器中Javascript单线程分析

    线程这个特性对于一门语言环境来说是尤其重要的,在Java/C++环境下都提供了多线程API操作. 但在Javascript中据说代码执行时单线程的,大量计算的逻辑会阻塞浏览器HTML渲染,但setTi ...

  4. PHP检测移动设备类mobile detection使用实例

    目前,一个网站有多个版本是很正常的,如PC版,3G版,移动版等等.根据不同的浏览设备我们需要定向到不同的版本中.不仅如此,我们有时候还需要根据不同的客户端加载不同的CSS,因此我们需要能够检测浏览设备 ...

  5. Android开发之Intent略解

    Intent是一种运行时绑定(run-time binding)机制,它能在程序运行过程中连接两个不同的组件.通过Intent,你的程序可以向Android表达某种请求或者意愿,Android会根据意 ...

  6. WINFORM 打开PDF

    这里使用 Adobe Read 组件 的方式 首先电脑上需要安装AdobeRead VS中添加COM引用 再在工具选项卡中添加Adobe PDF Read 组件即可 从工具箱中直接拖动组件到窗体中即可

  7. synchronized同步块和volatile同步变量

    Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量.这两种机制的提出都是为了实现代码线程的安全性.其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而 ...

  8. [原创]NDT方法在SLAM中的应用

    NDT概念 正态分布变换(Normal Distribution Transformation , NDT)概率密度函数( Probability Density Function, PDF)Firs ...

  9. jquery实时监测手机号是否符合规则,并根据手机号检测结果将提交按钮设为不同状态

    功能: 输入手机号,实时判断手机号输入的是否符合规则: 如果不合规则,则提交按钮为禁用状态,手机号信息不可提交,按钮显示灰色背景: 如果符合规则,则可提交所输入的手机号信息,并将按钮背景设成红色. 代 ...

  10. svg学习(六)line

    <line> 标签用来创建线条. <?xml version="1.0" standalone="no"?> <!DOCTYPE ...