最近想自己寫個手寫識別的小程序,然後又可能的話再試試數學公式識別什麼的,所以週末騰出時間寫了些代碼。
照例先在網上找了找有沒有現成的實現,發現了這篇文章http://blog.csdn.net/hellogv/article/details/5526284。把博主的代碼下載下來,調試了一下,發現基本功能實現了,但是性能很一般,決定在此代碼的基礎上繼續我的工作。
上面文章中的代碼只是簡單的比對當前輸入與訓練樣本中特徵的相似程度,取一個最大的作爲分類結果,多少有些簡單。
最樸素的手寫識別想法是在一個規定大小的區域內,比如20X20的像素區域內,進行神經網絡的訓練,那麼這個網絡的輸入層就有400個,還要加上一個常數,一共401個。然後設置一個隱藏層,輸出層一個節點就成。將標記過的手寫樣本輸入到網絡中,不斷優化參數,得到一個字符的神經網絡。
同時,還有一些手寫識別結合了筆畫順序與種類來輔助分類,爲了後續工作的開展,我先補充了記錄筆畫的代碼部分。
當前使用的手寫輸入設備是鼠標,圖像的大小爲40X40。爲了記錄筆畫順序,在源代碼中加入了MouseDown和MouseUp兩個時間的響應,並修改了MouseMove的響應,代碼如下:
privatevoid pbDraw_MouseDown(object sender, MouseEventArgs e)
{
mouse_hit= true;
if (clear_hit == 0)
{
mousehit.Push(0);
clear_hit++;
}
}
privatevoid pbDraw_MouseUp(object sender, MouseEventArgs e)
{
if(mouse_hit == true)
{
int count = mousehit.Peek();
StreamWriter sw = newStreamWriter(mg_fn, true);
Point p1;
sw.WriteLine(count);
while (mouseGesture.Count != 0)
{
p1 = mouseGesture.Peek();
sw.WriteLine(p1.X +"?" + p1.Y);
mouseGesture.Dequeue();
}
sw.Close();
count++;
mousehit.Push(count);
}
mouse_hit= false;
}
privatevoid pbDraw_MouseMove(object sender, MouseEventArgs e)
{
if(mouse_hit == true)
{
Point p1 = new Point { X = e.X,Y = e.Y};
clsHandWrite.Draw(e.X, e.Y);
mouseGesture.Enqueue(p1);
}
}
其中mouse_hit表示鼠標鍵是否被按下,true表示按下,false表示釋放。
clear_hit表示界面上的clear按鈕是否被按過,該按鈕每被按一次,代表一次訓練或識別結束,將筆畫計數器count清零。(這算是一個我的程序的一個假設吧,這個觸發關係以後還應該妥善處理一下,同時記錄筆畫的棧mousehit也應該隨着清空,避免溢出。)
每次鼠標鍵按下開始,到鼠標鍵釋放爲止,記錄中間鼠標滑過的座標點,記錄在mouseGesture中。鼠標鍵釋放後將mouseGesture中的點信息存入臨時文件mg_fn.txt中。
在主程序中加入一個將當前筆畫轉爲字符串的函數,同時修改Learn函數如下:
privateString GetCurrentMouseGesture()
{
Stringtmp = "";
StreamReadersr = new StreamReader(mg_fn, true);
while(!sr.EndOfStream)
{
tmp= tmp+ sr.ReadLine() + "!" ;
}
sr.Close();
returntmp;
}
publicvoid Learn(String name)
{
Stringmgrec = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase +"mgrec.txt";
StreamWritersw = new StreamWriter(fileName, true);
StreamWritersw_mg = new StreamWriter(mgrec, true);
sw.WriteLine(name+ " " + GetBMPContext(bmpDraw));
sw_mg.WriteLine(name+ " " + GetCurrentMouseGesture());
sw.Close();
sw_mg.Close();
}
爲了保持和原特徵文件處理的一致性,加入了函數GetCurrentMouseGesture,用於將當前的筆畫順序轉成字符串,其中mg_fn文件中行與行用"!"隔開,每組座標的兩個數用“?”隔開。
這樣基本工作就完成了。
下面要做的就是引入機器學習的相關內容,建立神經網絡學習,提高分類的準確性。
待續