1. 介绍 AI的通用文字识别可以对文档翻拍、街景翻拍等图片来源的文字检测和识别,可以集成在其他应用中,提供文字检测、识别的功能,并根据识别结果提供翻译、搜索等相关服务。该功能在一定程度上支持文本倾斜、拍摄角度倾斜、复杂光照条件以及复杂文本背景等场景的文字识别。通用文字识别详细介绍可参考
AI-通用文字识别,分词详细介绍可参考
AI-分词。
说明
- 分词文本限制在500字以内,编码格式必须为utf-8。
- 分词目前只支持中文语境。
- 支持处理的图片格式包括JPEG、JPG、PNG、GIF、BMP。
- 目前支持的语言有:中文、英文、日语、韩语、俄语、意大利语、西班牙语、葡萄牙语、德语,以及法语(将来会增加更多语种),但不支持手写字体识别。
本教程将通过以下内容为您展示如何实现基于AI的通用文字识别功能。
2. 搭建HarmonyOS环境
我们首先需要完成HarmonyOS开发环境搭建,可参照如下步骤进行。
- 安装DevEco Studio,详情请参考下载和安装软件。
- 设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:
- 开发者可以参考以下链接,完成设备调试的相关配置:
3. 代码结构解读
基于AI的通用文字识别示例教程主要内容包括:图片列表展示、输入文本、分词、通用文字识别、结果展示等功能,可在9 完整示例中查看工程代码。DevEco Studio工程代码结构如下:
- provider:PictureProvider图片适配类,获取所有图片,并将图片放到图片列表中。
- slice:MainAbilitySlice本示例教程主页面。
- util:工具类
- LogUtil是日志打印类,对HiLog日志进行了封装。
- WordRecognition是通用文字识别类,对图片中的文字进行识别并保存。
- WordSegment是分词类,对输入文本进行分词。
- MainAbility:主程序入口,DevEco Studio生成,未添加逻辑,不需变更。
- MyApplication:DevEco Studio生成,不需变更。
- resources:存放工程使用到的资源文件
- resourcesbaseelement中存放DevEco studio自动生成的配置文件string.json,不用变更。
- resourcesbasegraphic中存放页面样式文件:
background_ability_page.xml用于设置界面背景颜色。
background_ability_main.xml用于设置界面布局样式。
button_element.xml用于设置按钮样式。 - resourcesbaselayout中布局文件:
ability_main.xml用于展示图片和输入文本。
item_image_layout.xml用于设置图片滑动区域图片。 - resourcesbasemedia下存放图片资源(本教程使用了8张.jpg图片,开发者自行准备;icon.png由DevEco Studio生成不需变更)。
- config.json:配置文件。
4. 添加并展示图片 - 在"resourcesbasemedia"目录下添加8张jpg图片(分别命名为1-8.jpg),并加载图片id数组,代码如下:
- private int[] pictureLists = new int[]{ResourceTable.Media_1, ResourceTable.Media_2,
- ResourceTable.Media_3, ResourceTable.Media_4, ResourceTable.Media_5,
- ResourceTable.Media_6, ResourceTable.Media_7, ResourceTable.Media_8};
复制代码
- 获取图片id数组和MainAbilitySlice对象,代码如下:
- public PictureProvider(int[] pictureLists, Context context) {
- this.pictureLists = pictureLists;
- this.context = context;
- }
复制代码
- 展示图片到页面,代码如下:
- [url=home.php?mod=space&uid=2735960]@Override[/url]
- public Component getComponent(int var1, Component var2, ComponentContainer var3) {
- ViewHolder viewHolder = null;// Component中展示图片类
- Component component = var2;
- if (component == null) {
- component = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_item_image_layout,
- null, false);
- viewHolder = new ViewHolder();
- Component componentImage = component.findComponentById(ResourceTable.Id_select_picture_list);
- if (componentImage instanceof Image) {
- viewHolder.image = (Image) componentImage;
- }
- component.setTag(viewHolder);//设置需要展示的图片
- } else {
- if (component.getTag() instanceof ViewHolder) {
- viewHolder = (ViewHolder) component.getTag();
- }
- }
- if (viewHolder != null) {
- viewHolder.image.setPixelMap(pictureLists[var1]);
- }
- return component;
- }
复制代码
- 定义ViewHolder类,用于列表中展示图片,代码如下:
- private static class ViewHolder {
- Image image;
- }
复制代码
5. 识别图片中的文字 - 调用文字识别方法对图片文字进行识别,代码如下:
- wordRecognition(slice, pictureLists[index], handle); //index为待识别图片下标
- public void wordRecognition(Context context, int resId, MainAbilitySlice.MyEventHandle myEventHandle) {
- mediaId = resId;
- // 实例化ITextDetector接口
- iTextDetector = VisionManager.getTextDetector(context);
-
- // 实例化VisionImage对象image,并传入待检测图片pixelMap
- pixelMap = getPixelMap(resId);
- VisionImage image = VisionImage.fromPixelMap(pixelMap);
-
- // 定义VisionCallback<Text>回调,异步模式下用到
- VisionCallback<Text> visionCallback = getVisionCallback();
-
- // 定义ConnectionCallback回调,实现连接能力引擎成功与否后的操作
- ConnectionCallback connectionCallback = getConnectionCallback(image, visionCallback);
-
- // 建立与能力引擎的连接
- VisionManager.init(context, connectionCallback);
- }
复制代码
- 异步模式下回调方法,将图片中文字识别结果通过sendResult()方法发送到主线程,代码如下:
- private VisionCallback getVisionCallback() {
- return new VisionCallback<Text>() {
- @Override
- public void onResult(Text text) {
- sendResult(text.getValue());
- }
- };
- }
复制代码
- 连接引擎成功后进行文字识别,并将识别结果通过sendResult()方法发送到主线程,代码如下:
- private ConnectionCallback getConnectionCallback(VisionImage image, VisionCallback<Text> visionCallback) {
- return new ConnectionCallback() {
- @Override
- public void onServiceConnect() {
- // 实例化Text对象text
- Text text = new Text();
- // 通过TextConfiguration配置textDetector()方法的运行参数
- TextConfiguration.Builder builder = new TextConfiguration.Builder();
- builder.setProcessMode(VisionConfiguration.MODE_IN);
- builder.setDetectType(TextDetectType.TYPE_TEXT_DETECT_FOCUS_SHOOT); // 此处变量名将会被调整
- builder.setLanguage(TextConfiguration.AUTO);
- TextConfiguration config = builder.build();
- iTextDetector.setVisionConfiguration(config);
- // 调用ITextDetector的detect()方法
- if (!IS_ASYNC) {
- int result2 = iTextDetector.detect(image, text, null); // 同步
- sendResult(text.getValue());
- } else {
- int result2 = iTextDetector.detect(image, null, visionCallback); // 异步
- }
- }
-
- @Override
- public void onServiceDisconnect() {
- // 释放 成功:同步结果码为0,异步结果码为700
- if ((!IS_ASYNC && (result == 0)) || (IS_ASYNC && (result == IS_ASYNC_CODE))) {
- iTextDetector.release();
- }
- if (pixelMap != null) {
- pixelMap.release();
- pixelMap = null;
- }
- VisionManager.destroy();
- }
- };
- }
复制代码
说明
1.引擎使用TextDetectType.TYPE_TEXT_DETECT_FOCUS_SHOOT(聚焦拍照OCR)。
2.同步模式调用成功时,该函数返回结果码0。异步模式调用请求发送成功时,该函数返回结果码700。
3.同步模式下visionCallback为null,结果码由方法返回,检测识别结果由text中返回。
4.异步模式下visionCallback不为null,函数返回时text中的值无效(即:text参数为null),实际识别结果由回调函数visionCallback返回。
5.IS_ASYNC为boolean变量,同步模式时该值为false,异步模式时该值为true。 - 将文字识别结果发送到主线程(MainAbilitySlice类中接收),代码如下:
- public void sendResult(String value) {
- if (iTextDetector != null) {
- iTextDetector.release();
- }
- if (pixelMap != null) {
- pixelMap.release();
- pixelMap = null;
- VisionManager.destroy();
- }
- if (value != null) {
- maps.put(mediaId, value);
- }
- if ((maps != null) && (maps.size() == pictureLists.length)) {
- InnerEvent event = InnerEvent.get(1, 0, maps);
- handle.sendEvent(event);
- } else {
- wordRecognition(slice, pictureLists[index], handle);
- index++;
- }
- }
复制代码
6. 提取用户输入的关键词 - 获取MainAbilitySlice传递的环境参数并进行分词操作,同步方式调用sendResult()方法将分词结果发送到主线程,代码如下:
- public void wordSegment(Context context, String requestData, MainAbilitySlice.MyEventHandle myEventHandle) {
- slice = context; // MainAbilitySlice.this
- handle = myEventHandle; // MyEventHandle对象
-
- // 使用NluClient静态类进行初始化,通过异步方式获取服务的连接。
- NluClient.getInstance().init(context, new OnResultListener<Integer>() {
- @Override
- public void onResult(Integer resultCode) {
- if (!IS_ASYNC) {
- // 分词同步方法
- ResponseResult responseResult = NluClient.getInstance().getWordSegment(requestData,
- NluRequestType.REQUEST_TYPE_LOCAL);
- sendResult(responseResult.getResponseResult());
- release();
- } else {
- // 分词异步方法
- wordSegmentAsync(requestData);
- }
- }
- }, true);
- }
复制代码
说明
1.IS_ASYNC为boolean变量,同步模式时该值为false,异步模式时该值为true。
2.responseResult对象中code属性为0表示分词成功。 - 异步请求回调此方法,通过sendResult()方法将分词结果发送到主线程,代码如下:
- private void wordSegmentAsync(String requestData) {
- ResponseResult responseResult = NluClient.getInstance().getWordSegment(requestData,
- NluRequestType.REQUEST_TYPE_LOCAL, new OnResultListener<ResponseResult>() {
- @Override
- public void onResult(ResponseResult asyncResult) {
- sendResult(asyncResult.getResponseResult());
- release();
- }
- });
- }
复制代码
- 将分词结果发送到主线程中(MainAbilitySlice类中接收),代码如下:
- private void sendResult(String result) {
- List lists = null;// 分词识别结果
- // 将result中分词结果转换成list
- if (result.contains(""message":"success"")) {
- String words = result.substring(result.indexOf(WORDS) + STEP,
- result.lastIndexOf("]")).replaceAll(""", "");
- if ((words == null) || ("".equals(words))) {
- lists = new ArrayList(1);// 未识别到分词结果,返回"no keywords"
- lists.add("no keywords");
- } else {
- lists = Arrays.asList(words.split(","));
- }
- }
-
- InnerEvent event = InnerEvent.get(TWO, ZERO, lists);
- handle.sendEvent(event);
- }
复制代码
7. 根据关键词匹配图片 - 根据关键词匹配待识别图片,代码如下:
- private void matchImage(List<String> list) {
- Set<Integer> matchSets = new HashSet<>();
- for (String str: list) { // 遍历分词结果
- // imageInfos待识别图片通用文字识别结果
- for (Integer key : imageInfos.keySet()) {
- if (imageInfos.get(key).indexOf(str) != NEG_ONE) {
- matchSets.add(key);
- }
- }
- }
- // 获得匹配的图片
- matchPictures = new int[matchSets.size()];
- int i = 0;
- for (int match: matchSets) {
- matchPictures[i] = match;
- i++;
- }
- // 展示图片
- setSelectPicture(matchPictures, LIST_CONTAINER_ID_MATCH);
- }
复制代码
- 展示结果图片到页面,代码如下:
- private void setSelectPicture(int[] pictures, int id) {
- // 获取图片
- PictureProvider newsTypeAdapter = new PictureProvider(pictures, this);
-
- Component componentById = findComponentById(id);
- if (componentById instanceof ListContainer) {
- ListContainer listContainer = (ListContainer) componentById;
- listContainer.setItemProvider(newsTypeAdapter);
- }
- }
复制代码
最终实现效果
在"请输入关键词"下面的输入框中输入需要分词的关键词,点击【开始通用文字识别】按钮进行关键词搜索图片,您将会在"搜索结果"下方看到包含关键词的图片。
- 垃圾分类人人做 做好分类为人人
- 可回收物 其他垃圾
通过本教程的学习,你已学会如何使用AI能力中的通用文字识别和分词。