当前位置:首页 > 嵌入式 > 嵌入式软件
[导读] //========================================================================//TITLE:// 漫谈WinCE的手写识别技术(二)//AUTHOR:// norains//DATE:// Thursday 25-Januar

 //========================================================================

//TITLE:

// 漫谈WinCE的手写识别技术(二)

//AUTHOR:

// norains

//DATE:

// Thursday 25-January -2007

//Environment:

// EVC4.0 + Standard SDK

//========================================================================

在第一章的时候,已经介绍了识别的一般性过程,对于实际运用来说,是完全可行的;但从便利性角度出发,却不免显得烦琐:每次输入笔画都需留意点阵是否屏幕坐标系,每次读取返回的字符总要分配内存然后获取等等,诸如总总,代码写一次还好,如果多处运用多次编写多方维护,实在不是一件快乐的事情.

而我,最讨厌做复杂又要花费脑筋的东东;所以,为了让自己感觉得写代码是一件快乐的事情,自己又很高兴地将识别过程封装为一个类.至于是否达到简便的效果,不敢祈求大家苟同,只愿自己舒坦即可.

//////////////////////////////////////////////////////////////////////

// Recognizer.h: interface for the CRecognizer class. //

/////////////////////////////////////////////////////////////////////

#ifndef RECOGNIZER_H

#define RECOGNIZER_H

//===========================================================================

//Include file

#include "recog.h"

//=====================================================================================

//Choose the build type for the recognizing function

//--------------------------------------------------------------------------

#define RECOGNIZE_FUNCTION_FROM_DLL

//#define RECOGNIZE_FUNCTION_FROM_LIB

#ifndef RECOGNIZE_FUNCTION_FROM_LIB

#ifndef RECOGNIZE_FUNCTION_FROM_DLL

#define RECOGNIZE_FUNCTION_FROM_DLL

#endif

#endif

#ifdef RECOGNIZE_FUNCTION_FROM_DLL

#define RECOGNIZE_DLL_PATH TEXT("/WINDOWS/hwxcht.dll")

#endif

//=====================================================================================

//-----------------------------------------------------------------------------------[!--empirenews.page--]

//The data type

//The scale type for the coordinate

enum ScaleType

{

SCALE_APPWND,

SCALE_SCREEN

};

//------------------------------------------------------------------------------

class CRecognizer

{

public:

BOOL InputStroke(POINT *lpPnt, int iCount, ScaleType scale);

CRecognizer();

virtual ~CRecognizer();

int GetCharacter(WCHAR *pWchar, int iCount);

BOOL EndRecognize();

BOOL BeginRecognize();

BOOL Initialize(HWND hWnd,const RECT *prcWnd,ScaleType scale);

protected:

HRC m_hrc;

HWXGUIDE m_hwxGuide;

HWND m_hWndRecog;

ALC m_alc;

#ifdef RECOGNIZE_FUNCTION_FROM_DLL

typedef BOOL (WINAPI *DLL_HWXCONFIG)(void);

typedef HRC (WINAPI *DLL_HWXCREATE)(HRC = NULL);

typedef BOOL (WINAPI *DLL_HWXSETGUIDE)(HRC ,HWXGUIDE*);

typedef BOOL (WINAPI *DLL_HWXALCVALID)(HRC,ALC);

typedef BOOL (WINAPI *DLL_HWXALCPRIORITY)(HRC,ALC);

typedef BOOL (WINAPI *DLL_HWXSETCONTEXT)(HRC,WCHAR);

typedef BOOL (WINAPI *DLL_HWXINPUT)(HRC,POINT*,UINT, DWORD);

typedef BOOL (WINAPI *DLL_HWXENDINPUT)(HRC);

typedef BOOL (WINAPI *DLL_HWXPROCESS)(HRC);

typedef INT (WINAPI *DLL_HWXRESULTSAVAILABLE)(HRC);

typedef INT32 (WINAPI *DLL_HWXGETRESULTS)(HRC, UINT, UINT, UINT, HWXRESULTS*);

typedef BOOL (WINAPI *DLL_HWXDESTROY)(HRC);

DLL_HWXCONFIG HWXCONFIG;

DLL_HWXCREATE HWXCREATE;

DLL_HWXSETGUIDE HWXSETGUIDE;

DLL_HWXALCVALID HWXALCVALID;

DLL_HWXALCPRIORITY HWXALCPRIORITY;

DLL_HWXSETCONTEXT HWXSETCONTEXT;

DLL_HWXINPUT HWXINPUT;

DLL_HWXPROCESS HWXPROCESS;

DLL_HWXRESULTSAVAILABLE HWXRESULTSAVAILABLE;

DLL_HWXGETRESULTS HWXGETRESULTS;

DLL_HWXDESTROY HWXDESTROY;

DLL_HWXENDINPUT HWXENDINPUT;

#endif //RECOGNIZE_FUNCTION_FROM_DLL

#ifdef RECOGNIZE_FUNCTION_FROM_LIB

#define HWXCONFIG(void) HwxConfig(void)

#define HWXCREATE(hrc) HwxCreate(hrc)

#define HWXSETGUIDE(hrc,lpGuide) HwxSetGuide(hrc,lpGuide)

#define HWXALCVALID(hrc,alc) HwxALCValid(hrc,alc)

#define HWXALCPRIORITY(hrc,alc) HwxALCPriority(hrc,alc)

#define HWXSETCONTEXT(hrc,wContext) HwxSetContext(hrc,wContext)

#define HWXINPUT(hrc,lppnt,upoints,timestamp) HwxInput(hrc,lppnt,upoints,timestamp)

#define HWXPROCESS(hrc) HwxProcess(hrc)

#define HWXRESULTSAVAILABLE(hrc) HwxResultsAvailable(hrc)

#define HWXGETRESULTS(hrc,cAlt,iFirst,cBoxRes,rgBoxResults) HwxGetResults(hrc,cAlt,iFirst,cBoxRes,rgBoxResults)

#define HWXDESTROY(hrc) HwxDestroy(hrc)

#define HWXENDINPUT(hrc) HwxEndInput(hrc)

#endif //RECOGNIZE_FUNCTION_FROM_LIB

};

//============================================================================================

#endif // !defined RECOGNIZER_H

//////////////////////////////////////////////////////////////////////

// Recognizer.cpp: implementation of the CRecognizer class. //

//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "Recognizer.h"

//----------------------------------------------------------------

//Macro define

//The default value of hwxGuide

#define DEFAULT_HWXGUIDE_CHORZBOX 1[!--empirenews.page--]

#define DEFAULT_HWXGUIDE_CVERTBOX 1

#define DEFAULT_HWXGUIDE_CXOFFSET 1

#define DEFAULT_HWXGUIDE_CYOFFSET 1

//The default value of ALC

#define DEFAULT_ALC ALC_KANJI_ALL

//--------------------------------------------------------------------

// Construction/Destruction

CRecognizer::CRecognizer()

{

m_alc = NULL;

m_hrc = NULL;

m_hWndRecog = NULL;

memset(&m_hwxGuide,0,sizeof(m_hwxGuide));

}

CRecognizer::~CRecognizer()

{

}

//-----------------------------------------------------------------------

//Descriptiong:

// Initialize the recognizer

//

//Parameter:

// hWnd: [in] The handle of window to be recognized

// rcWnd: [in] The window area to be recognized

// scale: [in] The scale base of prcWnd point

//-----------------------------------------------------------------------

BOOL CRecognizer::Initialize(HWND hWnd,const RECT *prcWnd,ScaleType scale)

{

m_hWndRecog = hWnd;

m_alc = DEFAULT_ALC;

RECT rcWnd = {0};

switch(scale)

{

case SCALE_APPWND:

{

rcWnd = *prcWnd;

rcWnd.left *= 4;

rcWnd.right *= 4;

rcWnd.top *= 4;

rcWnd.bottom *= 4;

MapWindowPoints(hWnd,HWND_DESKTOP,(LPPOINT)(&rcWnd),(sizeof(RECT)/sizeof(POINT)));

break;

}

case SCALE_SCREEN:

{

rcWnd = *prcWnd;

break;

}

}

m_hwxGuide.cHorzBox = DEFAULT_HWXGUIDE_CHORZBOX;

m_hwxGuide.cVertBox = DEFAULT_HWXGUIDE_CVERTBOX;

m_hwxGuide.xOrigin = rcWnd.left;

m_hwxGuide.yOrigin = rcWnd.top;

m_hwxGuide.cxBox = rcWnd.right - rcWnd.left;

m_hwxGuide.cyBox = rcWnd.bottom - rcWnd.top;

m_hwxGuide.cxOffset = DEFAULT_HWXGUIDE_CXOFFSET;

m_hwxGuide.cyOffset = DEFAULT_HWXGUIDE_CYOFFSET;

m_hwxGuide.cxWriting = (rcWnd.right - rcWnd.left) - m_hwxGuide.cxOffset * 2;

m_hwxGuide.cyWriting = (rcWnd.bottom - rcWnd.top) - m_hwxGuide.cyOffset * 2;

m_hwxGuide.nDir = HWX_HORIZONTAL;

#ifdef RECOGNIZE_FUNCTION_FROM_DLL

HINSTANCE hInstDll;

hInstDll = LoadLibrary(RECOGNIZE_DLL_PATH);

if(hInstDll != NULL)

{

HWXCONFIG = (DLL_HWXCONFIG) GetProcAddress(hInstDll,TEXT("HwxConfig"));

HWXCREATE = (DLL_HWXCREATE) GetProcAddress(hInstDll,TEXT("HwxCreate"));

HWXSETGUIDE = (DLL_HWXSETGUIDE) GetProcAddress(hInstDll,TEXT("HwxSetGuide"));

HWXALCVALID = (DLL_HWXALCVALID) GetProcAddress(hInstDll,TEXT("HwxALCValid"));

HWXALCPRIORITY = (DLL_HWXALCPRIORITY) GetProcAddress(hInstDll,TEXT("HwxALCPriority"));[!--empirenews.page--]

HWXSETCONTEXT = (DLL_HWXSETCONTEXT) GetProcAddress(hInstDll,TEXT("HwxSetContext"));

HWXINPUT = (DLL_HWXINPUT) GetProcAddress(hInstDll,TEXT("HwxInput"));

HWXPROCESS = (DLL_HWXPROCESS) GetProcAddress(hInstDll,TEXT("HwxProcess"));

HWXRESULTSAVAILABLE = (DLL_HWXRESULTSAVAILABLE) GetProcAddress(hInstDll,TEXT("HwxResultsAvailable"));

HWXGETRESULTS = (DLL_HWXGETRESULTS) GetProcAddress(hInstDll,TEXT("HwxGetResults"));

HWXDESTROY = (DLL_HWXDESTROY) GetProcAddress(hInstDll,TEXT("HwxDestroy"));

HWXENDINPUT = (DLL_HWXENDINPUT) GetProcAddress(hInstDll,TEXT("HwxEndInput"));

}

else

{

return FALSE;

}

#endif //RECOGNIZE_FUNCTION_FROM_DLL

if(HWXCONFIG() == FALSE)

{

return FALSE;

}

return TRUE;

}

//-----------------------------------------------------------------------

//Descriptiong:

// Begin recognizing

//-----------------------------------------------------------------------

BOOL CRecognizer::BeginRecognize()

{

BOOL bRes = FALSE;

m_hrc = HWXCREATE();

if(m_hrc == NULL)

{

goto END;

}

bRes = HWXSETGUIDE(m_hrc,&m_hwxGuide);

if(bRes == FALSE)

{

goto END;

}

bRes = HWXALCVALID(m_hrc,m_alc);

if(bRes == FALSE)

{

goto END;

}

bRes = TRUE;

END:

return bRes;

}

//-----------------------------------------------------------------------

//Descriptiong:

// End recognizing

BOOL CRecognizer::EndRecognize()

{

BOOL bRes = FALSE;

//Destroy the recognizer

if(HWXDESTROY(m_hrc) == FALSE)

{

goto END;

}

bRes = TRUE;

END:

return bRes;

}

//Descriptiong:

// Get the character

//Parameters:

// pWchar: [out] The character get to be stored

// iCount: [in] The number of pWchar

//Return Values:

// 0: Failed

// >0: The number of the characters to return

int CRecognizer::GetCharacter(WCHAR *pWchar, int iCount)

{

int iGetNum = 0;

int i = 0;

HWXRESULTS *phwxResults;

//Because each HWXRESULTS after the first one could store two characters,

//so only allocate (iCount / 2 + 1)

int iNum = iCount / 2 + 1;

phwxResults = new HWXRESULTS[iNum];

memset(phwxResults,0,iNum * sizeof(HWXRESULTS));

//End the input

if(HWXENDINPUT(m_hrc) == FALSE)

{

goto END;

}

//Analyze the information

if(HWXPROCESS(m_hrc) == FALSE)[!--empirenews.page--]

{

goto END;

}

//Get the character from recognizer

if(HWXGETRESULTS(m_hrc,iCount,0,1,phwxResults) == FALSE)

{

goto END;

}

//Set the character to the stored buffer

for(i = 0; i < iNum; i++)

{

if(i == 0)

{

if(phwxResults[i].rgChar[0] != 0)

{

pWchar[iGetNum ++] = phwxResults[i].rgChar[0];

}

else

{

break;

}

}

else

{

//The indxBox member also store the character

if(phwxResults[i].indxBox != 0)

{

pWchar[iGetNum ++] = phwxResults[i].indxBox ;

}

else

{

break;

}

if(phwxResults[i].rgChar[0] != 0)

{

pWchar[iGetNum ++] = phwxResults[i].rgChar[0];

}

else

{

break;

}

}

}

END:

if(phwxResults != NULL)

{

delete [] phwxResults;

}

return iGetNum;

}

//Descriptiong:

// Input the stroke

//Parameter:

// lpPnt: [in] Pointer to the stroke POINT

// iCount: [in] The count of the lpPnt

// scale: [in] The scale base of lpPnt

BOOL CRecognizer::InputStroke(POINT *lpPnt, int iCount, ScaleType scale)

{

BOOL bRes = FALSE;

int i = 0;

POINT *pt;

pt = new POINT[iCount];

if(pt == NULL)

{

goto END;

}

for(i = 0; i < iCount; i++)

{

pt[i] = lpPnt[i];

if(scale == SCALE_APPWND)

{

//Convert to the screen scale

pt[i].x *= 4;

pt[i].y *= 4;

MapWindowPoints(m_hWndRecog, HWND_DESKTOP, &pt[i], 1);

}

}

//Input stroke

bRes = HWXINPUT(m_hrc,pt,iCount,0);

if(bRes == FALSE)

{

goto END;

}

bRes = TRUE;

END:

if(pt != NULL)

{

delete [] pt;

}

return bRes;

}

不知道大家看到这段代码有什么感觉,反正我是挺高兴的,因为让我从繁琐的识别过程中脱离出来.

关于代码,也许最让人疑惑的可能是这两个宏:RECOGNIZE_FUNCTION_FROM_DLL,RECOGNIZE_FUNCTION_FROM_LIB.

顾名思义,RECOGNIZE_FUNCTION_FROM_DLL表明识别函数调用是来源于动态链接库(DLL),同理,RECOGNIZE_FUNCTION_FROM_LIB则是编译的时候链接到lib库.为什么需要定义这两个宏呢?因为在标准的SDK下,如果直接包含"recog.h"后调用相关识别函数,是会报link错误.因为标准的SDK是不包含任何手写识别组件的.从调试的便利性来说,这时候如果只拷贝识别库到模拟器就可以顺利测试程序,绝对比重新定制一个包含手写识别引擎的系统要来得方便.

在示例代码中,因为是识别繁体中文,所以包含的动态链接库为:hwxcht.dll.如果需要识别其它文字,则只要更改该动态链接库名称即可.当然,还要更改DEFAULT_ALC宏,这个宏定义了识别的范围.

因为示例代码中的识别函数全部是宏定义,具体意义根据函数的来源而不同,所以RECOGNIZE_FUNCTION_FROM_DLL和RECOGNIZE_FUNCTION_FROM_LIB同一时间只能定义一个.如果两个都定义,毫无疑问,出错!^_^

最后,用伪代码做范例说明如何使用该封装类,以此做本章结尾:

CRecognizer recog;

Rect rcWnd;

/*rcWnd 获取应用窗口hWnd的大小*/

//初始化

//直接赋值窗口坐标,函数体内部会根据标志直接转换为屏幕坐标

recog.Initialize(hWnd,&rcWnd,SCALE_APPWND);[!--empirenews.page--]

//开始识别

recog.BeginRecognize();

POINT pt[200];

int iCount = 0;

/*获取笔画坐标给pt,坐标的数量储存在iCount中*/

//将笔画点阵传送给识别引擎

//如果有多个笔画,则每个笔画都需要调用该函数进行传入

recog.InputStroke(pt,iCount,SCALE_APPWND);;

//获取十个最接近的字符,iReturn是实际返回的字符数

WCHAR wChar[10];

int iReturn = recog.GetCharacter(wChar,10);

//结束识别

recog.EndRecognize();

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭