1. 介绍
AI的通用文字识别可以对文档翻拍、街景翻拍等图片来源的文字检测和识别,可以集成在其他应用中,提供文字检测、识别的功能,并根据识别结果提供翻译、搜索等相关服务。该功能在一定程度上支持文本倾斜、拍摄角度倾斜、复杂光照条件以及复杂文本背景等场景的文字识别。通用文字识别详细介绍可参考AI-通用文字识别,分词详细介绍可参考AI-分词。
🕮 说明
● 分词文本限制在500字以内,编码格式必须为utf-8。
● 分词目前只支持中文语境。
● 支持处理的图片格式包括JPEG、JPG、PNG、GIF、BMP。
● 目前支持的语言有:中文、英文、日语、韩语、俄语、意大利语、西班牙语、葡萄牙语、德语,以及法语(将来会增加更多语种),但不支持手写字体识别。
本教程将通过以下内容为您展示如何实现基于AI的通用文字识别功能。
2. 代码结构解读
基于AI的通用文字识别示例教程主要内容包括:图片列表展示、输入文本、分词、通用文字识别、结果展示等功能,可在7 完整示例代码中查看工程代码。DevEco Studio工程代码结构如下:
● provider:PictureProvider图片适配类,获取所有图片,并将图片放到图片列表中。
● slice:MainAbilitySlice本示例教程主页面。
● util:工具类
○ LogUtil是日志打印类,对HiLog日志进行了封装。
○ WordRecognition是通用文字识别类,对图片中的文字进行识别并保存。
○ WordSegment是分词类,对输入文本进行分词。
● MainAbility:主程序入口,DevEco Studio生成,未添加逻辑,不需变更。
● MyApplication:DevEco Studio生成,不需变更。
● resources:存放工程使用到的资源文件
○ resources\base\element中存放DevEco studio自动生成的配置文件string.json,不用变更。
○ resources\base\graphic中存放页面样式文件:
◼ ️background_ability_page.xml用于设置界面背景颜色。
◼ ️background_ability_main.xml用于设置界面布局样式。
◼ ️button_element.xml用于设置按钮样式。
○ resources\base\layout中布局文件:
◼ ️ability_main.xml用于展示图片和输入文本。
◼ ️item_image_layout.xml用于设置图片滑动区域图片。
resources\base\media下存放图片资源(本教程使用了8张.jpg图片,开发者自行准备;icon.png由DevEco Studio生成不需变更)。
● config.json:配置文件。
3. 添加并展示图片
(1)在"resources\base\media"目录下添加8张jpg图片(分别命名为1-8.jpg),并加载图片id数组,代码如下:
privateint[] pictureLists = newint[]{ResourceTable.Media_1, ResourceTable.Media_2,
ResourceTable.Media_3, ResourceTable.Media_4, ResourceTable.Media_5,
ResourceTable.Media_6, ResourceTable.Media_7, ResourceTable.Media_8};
1.
(2)获取图片id数组和MainAbilitySlice对象,代码如下:
publicPictureProvider(int[] pictureLists, Context context) {
this.pictureLists = pictureLists;
this.context = context;
}
(3)展示图片到页面,代码如下:
@Override
publicComponent getComponent(intvar1, 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]);
}
returncomponent;
}
(4)定义ViewHolder类,用于列表中展示图片,代码如下:
privatestaticclass ViewHolder {
Image image;
}
4. 识别图片中的文字
(1)调用文字识别方法对图片文字进行识别,代码如下:
wordRecognition(slice, pictureLists[index], handle); //index为待识别图片下标
publicvoid wordRecognition(Context context,intresId, MainAbilitySlice.MyEventHandle myEventHandle) {
mediaId = resId;
// 实例化ITextDetector接口
textDetector = VisionManager.getTextDetector(context);
// 实例化VisionImage对象image,并传入待检测图片pixelMap
pixelMap = getPixelMap(resId);
VisionImage image = VisionImage.fromPixelMap(pixelMap);
// 定义VisionCallback回调,异步模式下用到
VisionCallback visionCallback = getVisionCallback();
// 定义ConnectionCallback回调,实现连接能力引擎成功与否后的操作
ConnectionCallback connectionCallback = getConnectionCallback(image, visionCallback);
// 建立与能力引擎的连接
VisionManager.init(context, connectionCallback);
}
(2)异步模式下回调方法,将图片中文字识别结果通过sendResult()方法发送到主线程,代码如下:
private VisionCallback getVisionCallback() {
returnnew VisionCallback() {
@Override
publicvoid onResult(Text text) {
sendResult(text.getValue());
}
};
}
(3)连接引擎成功后进行文字识别,并将识别结果通过sendResult()方法发送到主线程,代码如下:
private ConnectionCallback getConnectionCallback(VisionImage image, VisionCallback visionCallback) {
returnnew ConnectionCallback() {
@Override
publicvoid 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();
textDetector.setVisionConfiguration(config);
// 调用ITextDetector的detect()方法
if (!IS_ASYNC) {
intresult2 = textDetector.detect(image, text,null); // 同步
sendResult(text.getValue());
} else{
intresult2 = textDetector.detect(image,null, visionCallback); // 异步
}
}
@Override
publicvoid onServiceDisconnect() {
// 释放 成功:同步结果码为0,异步结果码为700
if ((!IS_ASYNC && (result == 0)) || (IS_ASYNC && (result == IS_ASYNC_CODE))) {
textDetector.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类中接收),代码如下:
publicvoid sendResult(String value) {
if (textDetector != null) {
textDetector.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++;
}
}
5. 提取用户输入的关键词
(1)获取MainAbilitySlice传递的环境参数并进行分词操作,同步方式调用sendResult()方法将分词结果发送到主线程,代码如下:
publicvoid wordSegment(Context context, String requestData, MainAbilitySlice.MyEventHandle myEventHandle) {
slice = context; // MainAbilitySlice.this
handle = myEventHandle; // MyEventHandle对象
// 使用NluClient静态类进行初始化,通过异步方式获取服务的连接。
NluClient.getInstance().init(context, new OnResultListener() {
@Override
publicvoid onResult(IntegerresultCode) {
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表示分词成功。
(3)异步请求回调此方法,通过sendResult()方法将分词结果发送到主线程,代码如下:
private void wordSegmentAsync(String requestData) {
ResponseResult responseResult = NluClient.getInstance().getWordSegment(requestData,
NluRequestType.REQUEST_TYPE_LOCAL, new OnResultListener() {
@Override
publicvoid onResult(ResponseResult asyncResult) {
sendResult(asyncResult.getResponseResult());
release();
}
});
}
1.
(4)将分词结果发送到主线程中(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);
}
6. 根据关键词匹配图片
(1)根据关键词匹配待识别图片,代码如下:
private void matchImage(List list) {
Set matchSets = new HashSet<>();
for(String str: list) { // 遍历分词结果
// imageInfos待识别图片通用文字识别结果
for(Integerkey: imageInfos.keySet()) {
if (imageInfos.get(key).indexOf(str) != NEG_ONE) {
matchSets.add(key);
}
}
}
// 获得匹配的图片
matchPictures = new int[matchSets.size()];
inti = 0;
for(intmatch: matchSets) {
matchPictures[i] = match;
i++;
}
// 展示图片
setSelectPicture(matchPictures, LIST_CONTAINER_ID_MATCH);
}
(2)展示结果图片到页面,代码如下:
private void setSelectPicture(int[] pictures,intid) {
// 获取图片
PictureProvider newsTypeAdapter = new PictureProvider(pictures, this);
Component componentById = findComponentById(id);
if (componentById instanceof ListContainer) {
ListContainer listContainer = (ListContainer) componentById;
listContainer.setItemProvider(newsTypeAdapter);
}
}
最终实现效果
在"请输入关键词"下面的输入框中输入需要分词的关键词,点击【开始通用文字识别】按钮进行关键词搜索图片,您将会在"搜索结果"下方看到包含关键词的图片。
● 垃圾分类人人做 做好分类为人人
● 可回收物 其他垃圾
7. 完整示例代码
编写布局与样式
(1)base/graphic/background_ability_main.xml
ohos:shape="rectangle">
ohos:color="#FFFFFF"/>
(2)base/graphic/background_ability_page.xml
ohos:shape="rectangle">
ohos:color="#FFFAF0"/>
(3)base/graphic/button_element.xml
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:shape="rectangle">
ohos:radius="100"/>
ohos:color="#FF007DFE"/>
(4)base/layout/ability_main.xml
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical"
ohos:background_element="$graphic:background_ability_page"
>
ohos:id="$+id:text_helloworld"
ohos:height="match_content"
ohos:width="match_content"
ohos:background_element="$graphic:background_ability_main"
ohos:layout_alignment="horizontal_center"
ohos:text="关键词搜索图片"
ohos:text_size="30fp"
ohos:top_margin="5vp"
/>
ohos:id="$+id:picture_list"
ohos:height="match_content"
ohos:width="match_content"
ohos:background_element="$graphic:background_ability_main"
ohos:layout_alignment="horizontal_center"
ohos:text="图片列表"
ohos:text_size="20fp"
ohos:top_margin="15vp"
/>
ohos:id="$+id:picture_list_show"
ohos:height="200vp"
ohos:width="match_parent"
ohos:orientation="horizontal"
ohos:left_margin="5vp"
ohos:right_margin="5vp"
/>
ohos:id="$+id:word_seg_title"
ohos:height="match_content"
ohos:width="match_content"
ohos:background_element="$graphic:background_ability_main"
ohos:left_margin="5vp"
ohos:text="请输入关键词:"
ohos:text_size="25fp"
ohos:top_margin="10vp"
/>
ohos:id="$+id:word_seg_text"
ohos:height="match_content"
ohos:width="match_parent"
ohos:background_element="$graphic:background_ability_main"
ohos:hint="Enter a statement."
ohos:left_padding="5vp"
ohos:right_padding="5vp"
ohos:text_alignment="vertical_center"
ohos:text_size="20fp"
ohos:top_margin="5vp"/>
ohos:id="$+id:button_search"
ohos:width="match_content"
ohos:height="match_content"
ohos:text_size="20fp"
ohos:text="开始通用文字识别"
ohos:layout_alignment="horizontal_center"
ohos:top_margin="10vp"
ohos:top_padding="1vp"
ohos:bottom_padding="1vp"
ohos:right_padding="20vp"
ohos:left_padding="20vp"
ohos:text_color="white"
ohos:background_element="$graphic:button_element"
ohos:center_in_parent="true"
ohos:align_parent_bottom="true"
ohos:bottom_margin="5vp"/>
ohos:id="$+id:picture_list_result"
ohos:height="match_content"
ohos:width="match_content"
ohos:background_element="$graphic:background_ability_main"
ohos:layout_alignment="horizontal_center"
ohos:text="搜索结果"
ohos:text_size="20fp"
ohos:top_margin="5vp"
/>
ohos:id="$+id:picture_list_match"
ohos:height="200vp"
ohos:width="match_parent"
ohos:orientation="horizontal"
ohos:left_margin="5vp"
ohos:right_margin="5vp"
/>
(5)base/layout/item_image_layout.xml
ohos:height="200vp"
ohos:width="205vp">
ohos:id="$+id:select_picture_list"
ohos:height="200vp"
ohos:width="200vp"
ohos:layout_alignment="horizontal_center"
ohos:top_margin="1vp"
ohos:scale_mode="stretch"
/>
功能逻辑代码
(1)com/huawei/searchimagebykeywords/provider/PictureProvider
import com.huawei.searchimagebykeywords.ResourceTable;
import ohos.agp.components.BaseItemProvider;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.app.Context;
import java.util.Optional;
publicclass PictureProvider extends BaseItemProvider {
private int[] pictureLists;
private Context context;
/**
* picture provider
*
* @param pictureLists pictureLists
* @param context context
*/
publicPictureProvider(int[] pictureLists, Context context) {
this.pictureLists = pictureLists;
this.context = context;
}
@Override
publicintgetCount() {
returnpictureLists ==null? 0 : pictureLists.length;
}
@Override
publicObject getItem(intposition) {
returnOptional.of(this.pictureLists[position]);
}
@Override
publiclong getItemId(intposition) {
returnposition;
}
@Override
publicComponent getComponent(intvar1, Component var2, ComponentContainer var3) {
ViewHolder viewHolder = null;
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]);
}
returncomponent;
}
private staticclass ViewHolder {
Image image;
}
}
(2)com/huawei/searchimagebykeywords/slice/MainAbilitySlice
import com.huawei.searchimagebykeywords.ResourceTable;
import com.huawei.searchimagebykeywords.provider.PictureProvider;
import com.huawei.searchimagebykeywords.util.WordRecognition;
import com.huawei.searchimagebykeywords.util.WordSegment;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.ListContainer;
import ohos.agp.components.TextField;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
publicclass MainAbilitySlice extends AbilitySlice {
private staticfinalintLIST_CONTAINER_ID_SHOW = ResourceTable.Id_picture_list_show;
private staticfinalintLIST_CONTAINER_ID_MATCH = ResourceTable.Id_picture_list_match;
private staticfinalintNEG_ONE = -1;
private staticfinalintZERO = 0;
private staticfinalintONE = 1;
private staticfinalintTWO = 2;
private Context slice;
private EventRunner runner;
private MyEventHandle myEventHandle;
private int[] pictureLists = newint[]{ResourceTable.Media_1, ResourceTable.Media_2,
ResourceTable.Media_3, ResourceTable.Media_4, ResourceTable.Media_5,
ResourceTable.Media_6, ResourceTable.Media_7, ResourceTable.Media_8};
private Component selectComponent;
private intselectPosition;
private Button button;
private TextField textField;
private Map imageInfos;
private int[] matchPictures;
@Override
publicvoid onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
slice = MainAbilitySlice.this;
// 展示图片列表
setSelectPicture(pictureLists, LIST_CONTAINER_ID_SHOW);
// 所有图片通用文字识别
wordRecognition();
// 设置需要分词的语句
Component componentText = findComponentById(ResourceTable.Id_word_seg_text);
if (componentText instanceof TextField) {
textField = (TextField) componentText;
}
// 点击按钮进行文字识别
Component componentSearch = findComponentById(ResourceTable.Id_button_search);
if (componentSearch instanceof Button) {
button = (Button) componentSearch;
button.setClickedListener(listener -> wordSegment());
}
}
@Override
publicvoid onActive() {
super.onActive();
}
@Override
publicvoid onForeground(Intent intent) {
super.onForeground(intent);
}
// 设置图片选择区域
private void setSelectPicture(int[] pictures,intid) {
// 获取图片
PictureProvider newsTypeAdapter = new PictureProvider(pictures, this);
Component componentById = findComponentById(id);
if (componentById instanceof ListContainer) {
ListContainer listContainer = (ListContainer) componentById;
listContainer.setItemProvider(newsTypeAdapter);
}
}
// 通用文字识别
private void wordRecognition() {
initHandler();
WordRecognition wordRecognition = new WordRecognition();
wordRecognition.setParams(slice, pictureLists, myEventHandle);
wordRecognition.sendResult(null);
}
// 分词
private void wordSegment() {
// 组装关键词,作为分词对象
String requestData = "{\"text\":"+ textField.getText() +",\"type\":0}";
initHandler();
new WordSegment().wordSegment(slice, requestData, myEventHandle);
}
// 匹配图片
private void matchImage(List list) {
Set matchSets = new HashSet<>();
for(String str: list) {
for(Integerkey: imageInfos.keySet()) {
if (imageInfos.get(key).indexOf(str) != NEG_ONE) {
matchSets.add(key);
}
}
}
// 获得匹配的图片
matchPictures = new int[matchSets.size()];
inti = 0;
for(intmatch: matchSets) {
matchPictures[i] = match;
i++;
}
// 展示图片
setSelectPicture(matchPictures, LIST_CONTAINER_ID_MATCH);
}
private void initHandler() {
runner = EventRunner.getMainEventRunner();
if (runner == null) {
return;
}
myEventHandle = new MyEventHandle(runner);
}
publicclass MyEventHandle extends EventHandler {
MyEventHandle(EventRunner runner) throws IllegalArgumentException {
super(runner);
}
@Override
protected void processEvent(InnerEvent event) {
super.processEvent(event);
inteventId = event.eventId;
if (eventId == ONE) {
// 通用文字识别
if (event.object instanceof Map) {
imageInfos = (Map) event.object;
}
}
if (eventId == TWO) {
// 分词
if (event.object instanceof List) {
List lists = (List) event.object;
if ((lists.size() > ZERO) && (!"no keywords".equals(lists.get(ZERO)))) {
// 根据输入关键词 匹配图片
matchImage(lists);
}
}
}
}
}
}
(3)com/huawei/searchimagebykeywords/util/LogUtil
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
publicclass LogUtil {
private staticfinal String TAG_LOG ="LogUtil";
private staticfinal HiLogLabel LABEL_LOG = new HiLogLabel(0, 0, LogUtil.TAG_LOG);
private staticfinal String LOG_FORMAT ="%{public}s: %{public}s";
private LogUtil() {
}
publicstaticvoid info(String tag, String msg) {
HiLog.info(LABEL_LOG, LOG_FORMAT, tag, msg);
}
publicstaticvoid error(String tag, String msg) {
HiLog.info(LABEL_LOG, LOG_FORMAT, tag, msg);
}
}
(4)com/huawei/searchimagebykeywords/util/WordRecognition
import com.huawei.searchimagebykeywords.slice.MainAbilitySlice;
import ohos.ai.cv.common.ConnectionCallback;
import ohos.ai.cv.common.VisionCallback;
import ohos.ai.cv.common.VisionConfiguration;
import ohos.ai.cv.common.VisionImage;
import ohos.ai.cv.common.VisionManager;
import ohos.ai.cv.text.ITextDetector;
import ohos.ai.cv.text.Text;
import ohos.ai.cv.text.TextConfiguration;
import ohos.ai.cv.text.TextDetectType;
import ohos.app.Context;
import ohos.eventhandler.InnerEvent;
import ohos.global.resource.NotExistException;
import ohos.global.resource.Resource;
import ohos.global.resource.ResourceManager;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
publicclass WordRecognition {
private staticfinal boolean IS_ASYNC =false;
private staticfinalintIS_ASYNC_CODE = 700;
private Context slice;
private ITextDetector textDetector;
private PixelMap pixelMap;
private MainAbilitySlice.MyEventHandle handle;
private int[] pictureLists;
private intmediaId;
private Map maps = new HashMap<>();
private intindex;
private intresult;
publicvoid setParams(Context context,int[] pictureIds, MainAbilitySlice.MyEventHandle myEventHandle) {
slice = context;
pictureLists = pictureIds;
handle = myEventHandle;
}
publicvoid wordRecognition(Context context,intresId, MainAbilitySlice.MyEventHandle myEventHandle) {
mediaId = resId;
// 实例化ITextDetector接口
textDetector = VisionManager.getTextDetector(context);
// 实例化VisionImage对象image,并传入待检测图片pixelMap
pixelMap = getPixelMap(resId);
VisionImage image = VisionImage.fromPixelMap(pixelMap);
// 定义VisionCallback回调,异步模式下用到
VisionCallback visionCallback = getVisionCallback();
// 定义ConnectionCallback回调,实现连接能力引擎成功与否后的操作
ConnectionCallback connectionCallback = getConnectionCallback(image, visionCallback);
// 建立与能力引擎的连接
VisionManager.init(context, connectionCallback);
}
private VisionCallback getVisionCallback() {
returnnew VisionCallback() {
@Override
publicvoid onResult(Text text) {
sendResult(text.getValue());
}
@Override
publicvoid onError(inti) {
}
@Override
publicvoid onProcessing(floatv) {
}
};
}
private ConnectionCallback getConnectionCallback(VisionImage image, VisionCallback visionCallback) {
returnnew ConnectionCallback() {
@Override
publicvoid 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();
textDetector.setVisionConfiguration(config);
// 调用ITextDetector的detect()方法
if (!IS_ASYNC) {
intresult2 = textDetector.detect(image, text,null); // 同步
sendResult(text.getValue());
} else{
intresult2 = textDetector.detect(image,null, visionCallback); // 异步
}
}
@Override
publicvoid onServiceDisconnect() {
// 释放
if ((!IS_ASYNC && (result == 0)) || (IS_ASYNC && (result == IS_ASYNC_CODE))) {
textDetector.release();
}
if (pixelMap != null) {
pixelMap.release();
pixelMap = null;
}
VisionManager.destroy();
}
};
}
publicvoid sendResult(String value) {
if (textDetector != null) {
textDetector.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++;
}
}
// 获取图片
private PixelMap getPixelMap(intresId) {
ResourceManager manager = slice.getResourceManager();
byte[] datas = new byte[0];
try {
Resource resource = manager.getResource(resId);
datas = readBytes(resource);
resource.close();
} catch (IOException | NotExistException e) {
LogUtil.error("get pixelmap failed, read resource bytes failed, ", e.getLocalizedMessage());
}
ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
srcOpts.formatHint = "image/jpg";
ImageSource imageSource;
imageSource = ImageSource.create(datas, srcOpts);
ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
decodingOpts.desiredSize = new Size(0, 0);
decodingOpts.desiredRegion = new Rect(0, 0, 0, 0);
decodingOpts.desiredPixelFormat = PixelFormat.ARGB_8888;
pixelMap = imageSource.createPixelmap(decodingOpts);
returnpixelMap;
}
private staticbyte[] readBytes(Resource resource) {
final intbufferSize = 1024;
final intioEnd = -1;
ByteArrayOutputStream output= new ByteArrayOutputStream();
byte[] buffers = new byte[bufferSize];
byte[] results = new byte[0];
while (true) {
try {
intreadLen = resource.read(buffers, 0, bufferSize);
if (readLen == ioEnd) {
results = output.toByteArray();
break;
}
output.write(buffers, 0, readLen);
} catch (IOException e) {
LogUtil.error("OrcAbilitySlice.getPixelMap","read resource failed ");
break;
} finally {
try {
output.close();
} catch (IOException e) {
LogUtil.error("OrcAbilitySlice.getPixelMap","close output failed");
}
}
}
returnresults;
}
}
(5)com/huawei/searchimagebykeywords/util/WordSegment
import com.huawei.searchimagebykeywords.slice.MainAbilitySlice;
import ohos.ai.nlu.NluClient;
import ohos.ai.nlu.NluRequestType;
import ohos.ai.nlu.OnResultListener;
import ohos.ai.nlu.ResponseResult;
import ohos.app.Context;
import ohos.eventhandler.InnerEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
publicclass WordSegment {
private staticfinal boolean IS_ASYNC =true;
private staticfinal String WORDS ="words";
private staticfinalintZERO = 0;
private staticfinalintTWO = 2;
private staticfinalintSTEP = 8;
private Context slice;
private MainAbilitySlice.MyEventHandle handle;
publicvoid wordSegment(Context context, String requestData, MainAbilitySlice.MyEventHandle myEventHandle) {
slice = context;
handle = myEventHandle;
// 使用NluClient静态类进行初始化,通过异步方式获取服务的连接。
NluClient.getInstance().init(context, new OnResultListener() {
@Override
publicvoid onResult(IntegerresultCode) {
if (!IS_ASYNC) {
// 同步
ResponseResult responseResult = NluClient.getInstance().getWordSegment(requestData,
NluRequestType.REQUEST_TYPE_LOCAL);
sendResult(responseResult.getResponseResult());
release();
} else{
// 异步
wordSegmentAsync(requestData);
}
}
}, true);
}
private void wordSegmentAsync(String requestData) {
ResponseResult responseResult = NluClient.getInstance().getWordSegment(requestData,
NluRequestType.REQUEST_TYPE_LOCAL, new OnResultListener() {
@Override
publicvoid onResult(ResponseResult asyncResult) {
sendResult(asyncResult.getResponseResult());
release();
}
});
}
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);
lists.add("no keywords"); // 未识别到分词结果,返回"no keywords"
} else{
lists = Arrays.asList(words.split(","));
}
}
InnerEvent event = InnerEvent.get(TWO, ZERO, lists);
handle.sendEvent(event);
}
private void release() {
NluClient.getInstance().destroy(slice);
}
}
(6)com/huawei/searchimagebykeywords/MainAbility
import com.huawei.searchimagebykeywords.slice.MainAbilitySlice;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
publicclass MainAbility extends Ability {
@Override
publicvoid onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
}
}
(7)com/huawei/searchimagebykeywords/MyApplication
import ohos.aafwk.ability.AbilityPackage;
publicclass MyApplication extends AbilityPackage {
@Override
publicvoid onInitialize() {
super.onInitialize();
}
}
🕮 说明
以上代码仅demo演示参考使用,产品化的代码需要考虑数据校验和国际化。
8. 恭喜您
通过本教程的学习,您已学会如何使用AI能力中的通用文字识别和分词。
【编辑推荐】
【责任编辑:jianghua TEL:(010)68476606】
点赞 0