以下描述了如何使用灵云HWR能力。
1. HWR简介
HWR (HandWritten Recognition) 联机手写识别技术,可以将在手写设备上书写时产生的有序轨迹信息化转化为汉字内码。
2. 选择模块和能力
手写识别提供了三种模式:
- 单字识别,只能将一段输入的笔迹识别为一个单字。这种模式目前可支持87种语言的识别 (包括英文、阿拉伯数字、符号)。单字识别支持本地端识别和云端识别。 在某些确保一次输入一个单字的情况下,可以选用单字识别模式。
- 多字识别,支持叠写和行写模式,也即会自动将输入的笔迹进行切割,按照多字进行识别。 目前这种模式支持云端和本地,支持中文简繁体、英文、韩语、日语的识别(都包括英文、阿拉伯数字、符号等)。 一般都应该选用这种模式,包括云端和本地总共8种能力可以选择(HWR能力描述)。
- 笔势识别,输入的笔迹被识别为列表里50种笔势(笔势列表)中的一种,输出结果为对应的索引值,存于结果条目HWR_RECOG_RESULT_ITEM 中字段pszResult。
另外,手写识别还提供了一些开发手写识别应用时有用的辅助能力,例如获取联想词和拼音、模拟笔形等,目前只有本地端能力, 分别是 hwr.local.associateword 和 hwr.local.pinyin 能力,以及 hwr.local.penscript 能力。
无论使用何种能力,基础模块 hci_hwr都是需要的。 使用云端识别时,需要加上hci_hwr_cloud_recog模块; 需要使用本地端识别时,需要加上hci_hwr_local_recog模块; 需要使用联想词,需要加上hci_hwr_associate模块; 需要使用拼音,需要加上hci_hwr_pinyin模块; 需要使用笔形,需要加上hci_hwr_penscript模块。
3. 手写识别
一个手写识别的过程如下:
int nSessionId = -1;
char * pszSessionConfig = "capKey=hwr.local.freestylus";
short g_StrokeData[]=
{
103 ,283 ,105 ,283 ,107 ,283 ,113 ,283 ,120 ,283,
129 ,283 ,138 ,283 ,146 ,283 ,156 ,283 ,162 ,283,
...
-1 ,0 , -1, -1
};
char * strRecogConfig = "";
errCode =
hci_hwr_recog( nSessionId, g_StrokeData,
sizeof(g_StrokeData), pszRecogConfig, &hwrRecogResult );
手写笔迹的数据是一连串的坐标点,每个坐标点是两个short,分别是 x 和 y 坐标。如果是 (-1, 0) 表示一个笔画结束(抬笔),如果是 (-1, -1) 则表示整个字结束。
云端识别只需要将能力key改为相应的云端能力key即可。
4. 实时识别
缺省情况下,识别会话是不启动实时识别的,也即每次调用 hci_hwr_recog() 函数时所输入的笔迹数据被认为是完整的笔迹数据, 如果不是(-1,0)(-1,-1)结束,会认为数据非法。
而当启用实时识别时,对于每次连续的识别内容,可以多次调用hci_hwr_recog() 。每次调用追加输入新的数据, 每次输入的数据以(-1,0)结束,也即每次输入的笔画是完整的,可以一次输入多个笔画。 最后一次以(-1,0)(-1,-1)结束,表示整次识别结束。
启动实时识别时,需要在创建识别会话时,加入realtime=yes选项。
char * pszSessionConfig = "capKey=hwr.local.freestylus,realtime=yes";
int nSessionId;
while (true)
{
get_storke();
char * strRecogConfig = "";
errCode =
hci_hwr_recog( nSessionId, g_StrokeData, g_StrokeLen, pszRecogConfig, &hwrRecogResult );
...
if (is_last_stroke())
break;
}
实时识别时,每次调用本函数都会返回从头开始的完整结果,新输入的数据会导致切分发生变化, 因此后一次结果不一定是前次结果再追加字符,可能会更改掉部分前次结果。实时识别中每次返回的识别结果都需要释放。
- 注解
- 实时识别仅对 本地 多字 识别模式的能力起作用,也即本地多字能力才能设置realtime,否则会提示 HCI_ERR_CONFIG_UNSUPPORT.
5. 识别选项
识别时可以同时配置一些识别选项,来进一步控制识别流程,下面介绍部分主要选项:
- recogRange
使用 recogRange 可以将识别范围限制在有限的字符集内,例如可以设置 recogRange=alphabet, 则输出肯定在52个大小写英文字母中,如果设置 recogRange=gb, 则输出为简体汉字集合, 如果设置 recogRange=big5,则输出为繁体汉字集合。也可以采用 '+' 连接多个识别范围, 例如可以设置 recogRange=lower+number+gb。英文能力hwr.local.freestylus和hwr.cloud.freewrite.english 暂时不支持识别范围的设置,传入此参数不会返回HCI_ERR_CONFIG_UNSUPPORT,会在识别时忽略此参数,但若传入的值 非法,则会返回HCI_ERR_CONFIG_INVALID。英文连写能力hwr.local.freestylus.v7只支持大小写字母范围,即lower, upper, alphabet
- splitMode
在多字识别时,我们可以用splitMode设置行写或叠写模式。当应用的书写区域较宽时,可以配置splitMode=line, 表示采用行写模式,当书写区域较小时,可以配置splitMode=overlap,表示叠写模式。英文暂不支持叠写模式
- candNum
表示输出的候选结果数目。
其余选项请参见 hci_hwr_recog() 函数说明。
6. 提交确认结果
当用户选择了候选中的其它结果,可以考虑提交确认结果,来帮助灵云学习用户的笔迹习惯, 以便建立针对此用户的个性化模型。
当采用云端识别能力时,提交确认结果时会直接将确认结果发送到云端。由于发送结果可能会带来一定的延迟感, 因此最好放在一个后台线程中进行。
当采用本地识别能力时,提交的确认结果会缓存在本地,会在上传用户历史数据时一同上传。
7. 获取联想词
灵云手写能力提供了获取联想词的功能。
为了使用联想词功能,使用capkey=hwr.local.associateword(或其他能力)开启会话:
int nSessionId = -1;
string session_config = "capkey=hwr.local.associateword";
获取联想词的方法如下:
char * szWords = "中华人民";
{
}
上述代码的输出结果如下:
Associate result[0]: 共和国
Associate result[1]: 币
Associate result[2]: 政府
Associate result[3]: 法院
Associate result[4]: 群众
Associate result[5]: 网
Associate result[6]: 代表
Associate result[7]: 银行
Associate result[8]: 日报
Associate result[9]: 代表大会
Associate result[10]: 大学
Associate result[11]: 检察院
Associate result[12]: 币汇率
Associate result[13]: 解放军
Associate result[14]: 出版社
Associate result[15]: 生活
Associate result[16]: 大会堂
Associate result[17]: 医院
Associate result[18]: 政府关于
Associate result[19]: 广播电台
Associate result[20]: 族
Associate result[21]: 主
Associate result[22]: 间
Associate result[23]: 营
Associate result[24]: 事
Associate result[25]: 警
Associate result[26]: 众
Associate result[27]: 国
Associate result[28]: 工
Associate result[29]: 营企业
Associate result[30]: 航
Associate result[31]: 俗
Associate result[32]: 用
可以看到,获取联想词的时候会先按照输入串整体进行联想,然后依次从前去除字符进行联想, 例如,这里会先给出"共和国"(按照"中华人民"匹配),然后是"币"(按照"人民"匹配)等, 然后是"族"等(按照"民"匹配)等。(此特性可通过联想参数recursive进行打开或关闭,默认打开) 纯英文不支持此特性,中文或中英混杂时支持)
总的联想词的累计字数有一定限制,是由SDK内部确定的, 目前不能由开发者设置大小。
联想capkey中hwr.local.associateword支持英文词的联想功能(所需资源文件不同)。传入全英文请求时可以返回英文联想结果,例如:
string session_config = "capkey=hwr.local.associateword";
...
其输出为:
Associate result[0]: appal
Associate result[1]: appall
Associate result[2]: appalling
Associate result[3]: appallingly
Associate result[4]: apparatus
Associate result[5]: apparel
Associate result[6]: apparent
Associate result[7]: apparently
Associate result[8]: appeal
Associate result[9]: appealed
Associate result[10]: appealing
Associate result[11]: appeals
Associate result[12]: appear
Associate result[13]: appearance
Associate result[14]: appeared
Associate result[15]: appearing
Associate result[16]: appears
Associate result[17]: appease
Associate result[18]: appeased
Associate result[19]: appeasement
如果输入是中英文混杂的,仍会按照中文匹配方式,一个一个从前去除字符后进行联想。
联想词动态调整功能
hci_hwr_associate_words_adjust( MUST IN int nSessionId, OPT IN const char * pszConfig, MUST IN const char * pszWord )
支持中文的联想词动态调整,若输入的是词库中已有的词,则会使其出现位置提前。联想结果的排序是按词频数值进行的,词频有最大值, 如果多个词的词频都达到最大值,按照达到最大值的先后顺序,它们会被依次置顶。
若输入的是词库中没有的词,则插入词库,存于字典内的预留空间,字典大小不变,预留空间写满后较早插入的新词将被覆盖。
不支持英文联想词动态调整,当输入串为全部英文时,返回失败。
pszConfig 初始化配置串,ASCII字符串,以'\0'结束,保留接口,暂时无配置项。
pszWord 字符串指针,UTF-8格式,以'\0'为结束符,最少2个字符,最多15个字符(注意:不是15个字节)。
{
printf( "hci_hwr_associate_words_adjust success\n" );
}
else
{
printf(
"hci_hwr_associate_words_adjust return (%d:%s)\n", err_code ,
hci_get_error_info(err_code));
}
8. 获取拼音
灵云手写能力提供了获取拼音的功能(此功能目前仅在Windows平台上支持)。
开启会话:
int nSessionId = -1;
string session_config = "capkey=hwr.local.pinyin";
获取拼音:
char * szWords = "重";
{
}
上述代码的输出为:
Pinyin result[0] : chóng
Pinyin result[1] : zhòng
9. 笔形库功能
输出时支持笔形