歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> C#中調用Matlab人工神經網絡算法實現手寫數字識別

C#中調用Matlab人工神經網絡算法實現手寫數字識別

日期:2017/3/1 9:16:31   编辑:Linux編程

手寫數字識別實現

設計技術參數:通過由數字構成的圖像,自動實現幾個不同數字的識別,設計識別方法,有較高的識別率

關鍵字:二值化 投影 矩陣 目標定位 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();

}
}
}

運行結果

Copyright © Linux教程網 All Rights Reserved