以下描述了如何使用灵云OCR能力。
1. OCR简介
OCR(Optical Character Recognition)光学字符识别技术,是指用扫描仪或数码相机等光学设备, 获取文本资料的图像,然后对图像文件进行分析处理,获取上面的文字及版面信息的过程。
2. 选择模块和能力
灵云可以提供云端和本地端的识别能力,目前提供以下能力:
- ocr.cloud : 云端识别,支持中文简繁体识别(包括英文等)。
- ocr.cloud.template : 云端模板识别,支持身份证、增值税发票、行驶证、驾驶证的识别。
- ocr.cloud.bizcard : 云端名片识别。
- ocr.cloud.bankcard : 云端银行卡识别。
- ocr.local : 本地端识别,支持中文简繁体识别(包括英文等)。
- ocr.local.template.v6 : 本地模板识别能力。
- ocr.local.bizcard.v6 : 本地名片识别能力。
- ocr.local.bankcard.v7 : 本地银行卡能力。
无论使用云端或本地端的识别能力,基础模块 hci_ocr都是需要的。当使用云端能力时,需要加上hci_ocr_cloud_recog模块, 当需要使用本地端能力时,需要加上hci_ocr_local_recog模块。
3. 支持的图像
3.1 图像格式
OCR内部支持三种图像格式:
- 二值图像:每个像素点由1bit表示(0,1分别表示背景和文字)
- 256级灰度图像:每个像素点由1byte表示, 表示256级灰度
- 24位真彩色图像:每个像素点为RGB三种分量,每个分量由1byte表示。
同样幅面的图像,灰度图像的大小将是二值图像的8倍,而真彩色图像的大小将是二值图像的24倍, 尽管经过压缩,这一倍数可能会缩小,但灰度和彩色图像仍然要比二值图像大很多。 当使用云端识别功能时,图像需要传输到云端,因此图像的大小显得比较关键。 我们建议在可以使用二值图像的时候,尽量直接使用二值图像。例如在使用扫描仪的时候, 可以将扫描图像的类型设为二值,而非灰度或彩色,这样可以减少上传的流量。 当一定要使用灰度图像时,我们也提供了配置项,可以让在本地端进行二值化工作,之后再传送到云端。
3.2 二值化
OCR的核心引擎仅针对二值图像,因此即便上传的是灰度图像和彩色图像,也会先经过二值化的转换过程,再交给识别核心。 二值化过程可以在云端实现,也可以在发送往云端前进行预处理,即在本地进行二值化处理过程, 这样向云端传输时就可以传输二值化过的图像,可以大大减少流量。
目前也支持两种二值化方法,可以在识别、版面分析、倾斜校正的时候利用配置项 binarize进行指定:
- global: 全局二值化算法,主要针对通过扫描、截屏等获取的图像。
- adaptive (缺省): 局部自适应二值化算法,主要针对通过拍照、摄像头等获取的受光照影响较大图像, 这种图像无法使用全局一个统一的阈值来进行二值化。
global算法速度快,对于受光照影响小的图像效果较好。adpative算法速度较慢,但针对受光照影响大的图像效果好于全局方法。 需要开发者根据具体应用所面对的场景自行选择。
binarize配置项仅对彩色和灰度图像有效,如果给的是二值图像,此配置项将忽略。
3.3 图像文件格式
一个图像可以使用不同的文件格式进行存储,例如TIFF, BMP, JPG, PNG, GIF等。这些图像格式具有文件头, 标识了文件格式、图像的基本信息(例如宽、高、图像类型),并且对图像数据进行了压缩。 在使用时,开发者直接将这些格式的数据传给灵云OCR模块,灵云OCR模块会根据文件头自动判断文件格式, 并进行解压缩操作。
目前不支持多页TIFF类型的文件,多页TIFF只会处理第一页的内容。 目前Android不支持GIF格式以及TIFF格式文件。
3.4 截屏图像设置
针对截屏图像,由于和普通扫描或拍照图像不太一样,因此灵云SDK内部进行了特别的支持, 可以在识别、版面分析、倾斜校正的时候利用配置项 imageType 进行指定:
- normal(缺省): 普通图像
- screen: 截屏图像
4 设置图像
在识别或其他相关操作之前,需要将图像数据设置到识别会话中。系统提供了多种设置图像数据的方式。
4.1 直接设置图像数据
通过缓存设置要识别的图像
通过路径设置识别图像
在iOS平台下,还提供了直接将UIImage设置到会话中的功能:
UIImage * image = ...;
errCode = hci_ocr_set_image_by_uiImage( nSessionId, image );
要注意的是:在iOS平台上, hci_ocr_set_image_buffer() 和 hci_ocr_set_image_file() 两个函数也是通过UIImage的解码函数来进行图像数据或文件的解码,然后再利用 hci_ocr_set_image_by_uiImage() 进行设置的, 因此支持的文件类型和格式等同于UIImage所支持的格式,特别的,对于二值图像,UIImage解码时会将其解码为只有两个灰度级的灰度图像。
4.3 获取图像
应用可以获得解码后的图像。
- 注解
-
在iOS平台下,提供了直接获取可显示的UIImage的函数:
UIImage * uiImage;
errCode = hci_ocr_get_uiImage( nSessionId, &uiImage );
获得的uiImage即可用于显示或者保存。
4.4 保存图像
在Windows平台下,提供了保存图像的函数 hci_ocr_save_image_file(),可以将从 hci_ocr_get_image() 函数得到的OCR_IMAGE 数据保存为一个文件。
此函数会根据文件名的后缀,确定保存的图像格式。
在iOS平台上,请先获取到UIImage,然后利用UIImage的图像保存函数进行保存, hci_ocr_save_image_file() 函数在iOS平台上会返回 HCI_ERR_UNSUPPORT。
5. 识别
5.1 最简单的识别
在将图像数据设置给会话后,即可使用hci_ocr_recog()进行识别, 此时会将整张图像当成一个横排正文区域进行识别。通过返回的 OCR_RECOG_RESULT 结构获取识别结果。示例如下:
char * pszConfig = "";
errCode =
hci_ocr_recog( nSessionId, pszConfig, NULL, 0, &ocrRecogResult );
5.2 指定区域识别
可以在识别时手动指定区域的位置,识别将在指定的区域范围内进行识别,例如一张图片上有两栏, 则需要指定两个区域进行识别。
char * pszConfig = "";
regions[0].wRegionLang = OCR_RECOG_LANG_DEFAULT;
...
int nRegionCount = 2;
errCode =
hci_ocr_recog( nSessionId, pszConfig, ®ions, nRegionCount, &ocrRecogResult );
区域的类型,目前支持横排正文、竖排正文、表格和图片。图片区域将不参与识别,但最最后如果是输出详细信息 (参见 详细结果) 时,会作为一个区域节点出现,便于将来版面恢复时候的统一处理。
区域的语言,这里一般都指定为 OCR_RECOG_LANG_DEFAULT,表示使用能力和配置串确定的识别语种。 但如果碰到一个页面上有多种语言(例如有简体也有繁体、或者也有纯英文的区域), 则可以强制指定某个区域的语言。
由于下面介绍的自动版面分析和自动倾斜校正,都有一定的可能会出错,因此,如果开发者可以知道需要识别的位置, 或者可以设计UI让用户来确定识别区域,或者让用户在 hci_ocr_layout_analysis() 自动版面分析的结果上进行修正, 采用手工设置区域的方式进行识别是较好的方式。
5.3 自动版面分析
开发者可以直接让灵云OCR能力来自动进行版面分析操作,也即分析出图像中有几个区域,每个区域的位置和类型是什么 (目前自动版面分析不会检测出区域的语种,也即结果都是 OCR_RECOG_LANG_DEFAULT)。
char * pszConfig = "autoLayout=yes";
errCode =
hci_ocr_recog( nSessionId, pszConfig, NULL, 0, &ocrRecogResult );
手动指定区域位置是优先的,也即如果指定了区域位置,autoLayout的配置项不被支持。
5.4 自动倾斜校正
灵云OCR能力还可以自动进行倾斜校正的操作,如果图像有倾斜,会自动纠偏后再进行识别。
char * pszConfig = "autoDeskew=yes";
errCode =
hci_ocr_recog( nSessionId, pszConfig, NULL, 0, &ocrRecogResult );
手动指定区域位置是优先的,也即如果指定了区域位置,autoDeskew的配置项不被支持,因为如果自动纠偏了, 指定区域的位置实际上是会错位的。
自动倾斜校正和自动版面分析可以一起指定。指定时,会先进行纠偏然后进行版面分析,最后再进行识别。
5.5 识别选项
主要的一些识别选项如下:
- recogRang
如果图片中的文字是简体字符,可以设置 recogRange=gb, 可以识别国标一二级汉字,总共6763个汉字。 如果图片中的文字是繁体的,可以设置 recogRange=big5, 可以识别Big5汉字,总共13060汉字。 此选项仅针对 ocr.cloud 能力有效。如果图片中的文字是纯英文的,请直接使用 ocr.cloud.english 能力。
- detailResult
缺省情况下 detailResult=no,识别只返回识别结果的文本串。如果设置detailResult=yes,则会返回详细的节点信息。 具体参见 详细结果。由于输出详细结果将使传输的数据大大增加,因此,仅在必须的时候再使用此选项。
- autoLayout / autoDeskew
自动版面分析和自动倾斜纠正的配置项,缺省情况下都是no,设为yes的情况上面已经做了介绍。
- binarize
设置二值化的方法,参见二值化。
- imageType
设置图像是否是截屏图像,参见 截屏图像。
- localProcess
采用云端能力进行处理时,是否先做本地预处理(现在主要是指二值化)
其它选项请详见 hci_ocr_recog() 函数的说明。
6. 版面分析
灵云OCR能力可以完成自动版面分析的工作。
如上所述,用户可以在这里返回的区域信息的基础上进行修正,然后再手工指定区域进行识别。
主要的一些版面分析选项如下:
- binarize
设置二值化的方法,参见二值化。
- imageType
设置图像是否是截屏图像,参见 截屏图像。
- localProcess
采用云端能力进行处理时,是否先做本地预处理(现在主要是指二值化)
7. 倾斜校正
灵云OCR能力可以完成倾斜校正的工作。
主要的一些倾斜校正选项如下:
- adjustImage
如果设为no, 本函数只会返回倾斜角度。如果设为yes,将会进行图像数据的倾斜校正操作,此时再通过 hci_ocr_get_image() 函数可以获得校正后的图像数据。
- binarize
设置二值化的方法,参见二值化。
- imageType
设置图像是否是截屏图像,参见 截屏图像。
- localProcess
采用云端能力进行处理时,是否先做本地预处理(现在主要是指二值化)
8. 详细结果
灵云OCR模块除了可以返回简单的识别结果文本串外,还能返回详细的结果信息,只需要在配置串中将detailResult设为yes。
详细信息是由一个节点数组组成,节点有如下类型:
- 页面节点 (OCR_RECOG_NODE_PAGE)
页面节点的信息包括:图像的宽、高,如果经过了自动倾斜校正,其校正的角度。
- 区域节点 (OCR_RECOG_NODE_REGION)
区域节点的信息包括:区域的类型,区域的矩形坐标,识别此区域时所用的语种。
- 表格单元节点 (OCR_RECOG_NODE_CELL)
表格单元节点的信息包括:表格单元的外界矩形。
这种类型的节点只有在区域是表格的情况下才会有,否则没有这一级,区域节点下面将直接跟行节点。
- 行节点 (OCR_RECOG_NODE_LINE)
行节点的信息包括:此行的基线坐标(如果是横排文字,表示上边线,竖排版则表示左边线),此行的大小 (横排表示行高,竖排表示行宽),此行字符的平均大小。
- 字符节点 (OCR_RECOG_NODE_CHAR)
字符节点的信息包括:识别的字符,候选字符,是否可信(置信度是否足够高),字符的外接矩形坐标。
由于空白字符不使用字符节点表示,因此如果此字符节点前面有一些空白(例如段首),这里也会给出前面的空格字符数。
一个典型的节点数组如下:
页面节点
区域节点1
行节点1
字符节点1
字符节点2
...
字符节点N
行节点2
字符节点1
...
...
区域节点2(表格区域)
表格单元节点1
行节点1
字符节点1
字符节点2
...
字符节点N
行节点2
...
...
表格单元节点2
...
...
...
开发者可以利用这里给出的详细信息,进行版面还原的工作。
9 模板识别
1、 支持的能力
ocr.cloud.template 云端模板识别能力
ocr.local.template.v6 本地模板识别能力
2、示例
int tempalte_id = -1;
if (cap_key.find("local.template") != string::npos)
{
string template_file = data_path + "/templates/IdCard/IDCard_EN.xml";
string strConfig;
{
return;
}
printf("hci_ocr_load_template success! \n");
}
string image_file = test_data_path;
if (cap_key.find("template") != string::npos)
image_file += "/IDCard.jpg";
else if (cap_key.find("bizcard") != string::npos)
image_file += "/BizCard.jpg";
else if (cap_key.find("bankcard") != string::npos)
image_file += "/BankCard.jpg";
else
image_file += "/ocr.jpg";
string recog_config = "";
if (cap_key.find("template") != string::npos)
{
if (cap_key.find("local.template") != string::npos)
{
char chTmp[32] = {0};
sprintf(chTmp,"%d",tempalte_id);
recog_config += (",templateId="+string(chTmp));
}
else
{
recog_config += ",property=idcard";
}
recog_config += ",templateIndex=0,templatePageIndex=0";
}
Recog(cap_key, recog_config, image_file);
if ( tempalte_id != -1 )
{
printf("hci_ocr_unload_template\n");
}
10 名片识别
1、 支持的能力
ocr.cloud.bizcard 云端名片识别能力
ocr.local.bizcard.v6 本地名片识别能力
2、示例
string image_file = test_data_path;
if (cap_key.find("template") != string::npos)
image_file += "/IDCard.jpg";
else if (cap_key.find("bizcard") != string::npos)
image_file += "/BizCard.jpg";
else if (cap_key.find("bankcard") != string::npos)
image_file += "/BankCard.jpg";
else
image_file += "/ocr.jpg";
Recog(cap_key, recog_config, image_file);
11 银行卡识别
1、 支持的能力
ocr.cloud.bankcard ocr.local.bankcard.v7 本地银行卡识别能力
2、示例
string image_file = test_data_path;
if (cap_key.find("template") != string::npos)
image_file += "/IDCard.jpg";
else if (cap_key.find("bizcard") != string::npos)
image_file += "/BizCard.jpg";
else if (cap_key.find("bankcard") != string::npos)
image_file += "/BankCard.jpg";
else
image_file += "/ocr.jpg";
Recog(cap_key, recog_config, image_file);
12 通用识别模块
示例
int session_id = -1;
string session_config = "capkey=" + cap_key;
{
return false;
}
printf( "hci_ocr_session_start success\n" );
HciExampleComon::FileReader image_data;
if (!image_data.Load(image_file.c_str()))
{
printf("load image file failed.\n");
return false;
}
printf("load image file success\n");
{
printf("hci_ocr_set_image_by_decode_buffer failed(%d)\n", err_code);
return false;
}
printf("hci_ocr_set_image_by_decode_buffer success\n");
printf("recog_config is %s\n",recog_config.c_str());
err_code =
hci_ocr_recog(session_id, recog_config.c_str() , NULL, 0, &ocrRecogResult);
{
printf("hci_ocr_recog success\n");
PrintOcrResult( ocrRecogResult );
}
else
{
}