漫談WinCE的手寫識(shí)別技術(shù)(一)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
//========================================================================
//TITLE:
// 漫談WinCE的手寫識(shí)別技術(shù)(一)
//AUTHOR:
// norains
//DATE:
// Wednesday 24-January -2007
//Environment:
// EVC4.0 + Standard SDK
//========================================================================
WinCE從4.0開始,集成了手寫識(shí)別輸入法,可以識(shí)別繁體中文,日文和韓文.因此如果在WinCE下采用相應(yīng)的API函數(shù)重寫上述三種語言的手寫識(shí)別輸入似乎顯得多此一舉.但多余并不代表沒有了解的價(jià)值,今天,就讓我們抽絲剝繭來探究WinCE下的手寫識(shí)別吧!
大體上來說,調(diào)用WinCE自帶的識(shí)別引擎進(jìn)行文字識(shí)別需要經(jīng)過如下十個(gè)步驟:
1.調(diào)用HwxConfig ()函數(shù)初始化識(shí)別引擎.在每個(gè)應(yīng)用程序中,該初始化只需要調(diào)用一次.
2.調(diào)用HwxCreate()創(chuàng)建識(shí)別引擎句柄.
函數(shù)原型為:HRC HwxCreate(HRC hrc).該函數(shù)有個(gè)形參hrc,保存的是已存在的識(shí)別引擎句柄.如果傳入該形參,則可以根據(jù)已存在的引擎的設(shè)置來創(chuàng)建新的識(shí)別引擎.當(dāng)然通常情況下我們僅僅是創(chuàng)建一個(gè)新的引擎,所以該函數(shù)更多情況下是不使用形參:
3.調(diào)用HwxSetGuide()函數(shù)來設(shè)置識(shí)別框的范圍.
設(shè)置該識(shí)別框范圍的重要性不言而喻,因?yàn)槿绻O(shè)置不恰當(dāng),則直接導(dǎo)致識(shí)別出錯(cuò)甚至無法識(shí)別.
該函數(shù)傳入的形參是一個(gè)HWXGUIDE結(jié)構(gòu),該結(jié)構(gòu)包含了識(shí)別框的一切信息:
typedef struct tagHWXGUIDE {
UINT cHorzBox;
UINT cVertBox;
INT xOrigin;
INT yOrigin;
UINT cxBox;
UINT cyBox;
UINT cxOffset;
UINT cyOffset;
UINT cxWriting;
UINT cyWriting;
UINT cyMid;
UINT cyBase;
UINT nDir;
} HWXGUIDE, *PHWXGUIDE;
如果用文字來描述各個(gè)形參的含義,我實(shí)在沒這個(gè)能力讓語言讀起來不覺得乏味,所以最簡單最直接最直觀的方法,我還是用圖片來標(biāo)識(shí)出各個(gè)參數(shù)的含義,至少應(yīng)該不會(huì)讓腦袋覺得發(fā)暈:
xOriginy,Origin分別定義了識(shí)別框的起始坐標(biāo),而cxBox,cyBox則分別定義了識(shí)別框的長度和寬度.需要注意的是,這四個(gè)參數(shù)是以屏幕坐標(biāo)為基準(zhǔn),如果我們獲得的是應(yīng)用程序窗口的坐標(biāo),在賦值之前,我們需要調(diào)用MapWindowPoints()進(jìn)行轉(zhuǎn)換.當(dāng)然,相同的道理也同樣運(yùn)用于該結(jié)構(gòu)的其它形參.
nDir定義了書寫的順序,我們一般使用HWX_HORIZONTAL,表明書寫方式是水平書寫.當(dāng)然,如果有特殊要求,我們還可以設(shè)置HWX_BIDIRECTIONAL或HWX_VERTICAL.
4.調(diào)用HwxALCValid()和HwxALCPriority()定義識(shí)別的標(biāo)準(zhǔn).
HwxALCValid()用來定義識(shí)別字符的范圍,HwxALCPriority()則是定義返回字符的優(yōu)先級(jí).
根據(jù)幫助文檔,可以識(shí)別的字符文字為:簡體中文,繁體中文,日文,韓文和英文.但在實(shí)際使用中,卻是無法正確識(shí)別簡體中文,這不能不說是一個(gè)遺憾.在平時(shí)應(yīng)用中,我們一般只需識(shí)別一種文字,此時(shí)我們可以只是簡單地設(shè)置HwxALCValid()即可:[!--empirenews.page--]
HwxALCValid(hrc,ALC_KANJI_ALL); //識(shí)別漢字
5.調(diào)用HwxSetContext()設(shè)置前文,提高文字識(shí)別率.如果沒有前文,可以不調(diào)用該函數(shù).
6.調(diào)用HwxInput()加入文字筆畫.如果文字是多筆畫,則應(yīng)多次調(diào)用該函數(shù).
函數(shù)原型是:
BOOL HwxInput(
HRC hrc,
POINT* lppnt,
UINT upoints,
DWORD timestamp
);
lppnt是輸入的筆畫坐標(biāo),upoints是坐標(biāo)的個(gè)數(shù),和HWXGUIDE的參數(shù)一樣,這里的坐標(biāo)也是屏幕坐標(biāo)系.timestamp是時(shí)間,一般情況下,我們可以設(shè)置為0.
需要注意的是,如果是多筆畫的文字,最好不要一次性將所有筆畫點(diǎn)陣通過HwxInput()輸入,否則最后的識(shí)別結(jié)果將會(huì)大相徑庭.因?yàn)樽R(shí)別引擎是一筆一劃進(jìn)行輸入識(shí)別的,如果多筆畫文字一次性輸入,引擎可能將所有筆畫當(dāng)成一個(gè)筆畫,從而導(dǎo)致識(shí)別結(jié)果異常不準(zhǔn)確.
7.調(diào)用HwxEndInput()告知引擎筆畫輸入結(jié)束,即將要進(jìn)行識(shí)別部分.
8.調(diào)用HwxProcess()讓引擎進(jìn)行識(shí)別處理.
9.調(diào)用HwxResultsAvailable()獲取識(shí)別的字符數(shù).
根據(jù)文檔,HwxResultsAvailable()返回識(shí)別的字符數(shù).然而在WinCE4.2中,調(diào)用hwxcht.dll的話,任何時(shí)候都是返回為0值,即使之后的函數(shù)能返回識(shí)別字符也依然如此.文檔中描述,該函數(shù)如果返回的是-1,則代表調(diào)用失敗,其它值代表可供使用的字符數(shù).也許是WinCE4.2下識(shí)別引擎不完善的緣故,該函數(shù)根本沒有發(fā)揮文檔所描述的作用.
10.調(diào)用HwxGetResults()獲取結(jié)果.
INT32 HwxGetResults(
HRC hrc,
UINT cAlt,
UINT iFirst,
UINT cBoxRes,
HWXRESULTS* rgBoxResults
);
初看起來,該函數(shù)形參似乎特別復(fù)雜,但實(shí)際上并非如此.
根據(jù)文檔,cAlt是期望的輪流返回的字符,iFirst是想要返回字符的索引,cBoxRes是返回的字符個(gè)數(shù).但實(shí)際上,cAlt起主導(dǎo)作用,比如說cBoxRes設(shè)置為1,而cAlt設(shè)置為10,則返回的字符個(gè)數(shù)依然為10.所以我在平常使用中,一般是將iFirst設(shè)為0,cBoxRes設(shè)為1,而cAlt設(shè)為所需返回的字符個(gè)數(shù).
rgBoxResults指向儲(chǔ)存字符的緩沖區(qū).不過,返回結(jié)果比較有意思,除了第一個(gè)rgBoxResults以外的所有結(jié)構(gòu)的indxBox成員都儲(chǔ)存了返回字符.
比如返回五個(gè)字符‘與子于飛干‘,則rgBoxResults的數(shù)組列數(shù)值為:
rgBoxResults[0].indxBox : 0
rgBoxResults[0].rgChar[0] : ‘與‘
rgBoxResults[1].indxBox : ‘子‘
rgBoxResults[1].rgChar[0] : ‘于‘
rgBoxResults[2].indxBox : ‘飛‘
rgBoxResults[2].rgChar[0] : ‘干‘
11.調(diào)用 HwxDestroy()銷毀引擎,本次識(shí)別過程結(jié)束.如果需要繼續(xù)識(shí)別文字,從步驟2重新開始.