`目标:鸿蒙上实现AI文字识别
1.核心MainAbilitySlice类文件如下:
- public class MainAbilitySlice extends AbilitySlice {
- private static final int LIST_CONTAINER_ID_SHOW = ResourceTable.Id_picture_list_show;
- private static final int LIST_CONTAINER_ID_MATCH = ResourceTable.Id_picture_list_match;
- private static final int NEG_ONE = -1;
- private static final int ZERO = 0;
- private static final int ONE = 1;
- private static final int TWO = 2;
- private Context slice;
- private EventRunner runner;
- private MyEventHandle myEventHandle;
- private int[] pictureLists = new int[]{ResourceTable.Media_icon_1, ResourceTable.Media_icon_2};
- private Component selectComponent;
- private int selectPosition;
- private Button button;
- private TextField textField;
- private Map<Integer, String> imageInfos;
- private int[] matchPictures;
- @Override
- public void 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
- public void onActive() {
- super.onActive();
- }
- @Override
- public void onForeground(Intent intent) {
- super.onForeground(intent);
- }
- // 设置图片选择区域
- 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);
- }
- }
- // 通用文字识别
- 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<String> list) {
- Set<Integer> matchSets = new HashSet<>();
- for (String str: list) {
- 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 initHandler() {
- runner = EventRunner.getMainEventRunner();
- if (runner == null) {
- return;
- }
- myEventHandle = new MyEventHandle(runner);
- }
- public class MyEventHandle extends EventHandler {
- MyEventHandle(EventRunner runner) throws IllegalArgumentException {
- super(runner);
- }
- @Override
- protected void processEvent(InnerEvent event) {
- super.processEvent(event);
- int eventId = event.eventId;
- if (eventId == ONE) {
- // 通用文字识别
- if (event.object instanceof Map) {
- imageInfos = (Map) event.object;
- }
- }
- if (eventId == TWO) {
- // 分词
- if (event.object instanceof List) {
- List<String> lists = (List) event.object;
- if ((lists.size() > ZERO) && (!"no keywords".equals(lists.get(ZERO)))) {
- // 根据输入关键词 匹配图片
- matchImage(lists);
- }
- }
- }
- }
- }
- }
复制代码2.PictureProvider.class文件
- public class PictureProvider extends BaseItemProvider {
- private int[] pictureLists;
- private Context context;
- /**
- * picture provider
- *
- * [url=home.php?mod=space&uid=3142012]@param[/url] pictureLists pictureLists
- * @param context context
- */
- public PictureProvider(int[] pictureLists, Context context) {
- this.pictureLists = pictureLists;
- this.context = context;
- }
- @Override
- public int getCount() {
- return pictureLists == null ? 0 : pictureLists.length;
- }
- @Override
- public Object getItem(int position) {
- return Optional.of(this.pictureLists[position]);
- }
- @Override
- public long getItemId(int position) {
- return position;
- }
- @Override
- public Component getComponent(int var1, 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]);
- }
- return component;
- }
- private static class ViewHolder {
- Image image;
- }
- }
复制代码3.WordRecognition类文件和WordSegment类文件
- public class WordRecognition {
- private static final boolean IS_ASYNC = false;
- private static final int IS_ASYNC_CODE = 700;
- private Context slice;
- private ITextDetector textDetector;
- private PixelMap pixelMap;
- private MainAbilitySlice.MyEventHandle handle;
- private int[] pictureLists;
- private int mediaId;
- private Map maps = new HashMap<>();
- private int index;
- private int result;
- public void setParams(Context context, int[] pictureIds, MainAbilitySlice.MyEventHandle myEventHandle) {
- slice = context;
- pictureLists = pictureIds;
- handle = myEventHandle;
- }
- public void wordRecognition(Context context, int resId, MainAbilitySlice.MyEventHandle myEventHandle) {
- mediaId = resId;
- // 实例化ITextDetector接口
- textDetector = 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);
- }
- private VisionCallback getVisionCallback() {
- return new VisionCallback<Text>() {
- @Override
- public void onResult(Text text) {
- sendResult(text.getValue());
- }
- @Override
- public void onError(int i) {
- }
- @Override
- public void onProcessing(float v) {
- }
- };
- }
- 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();
- textDetector.setVisionConfiguration(config);
- // 调用ITextDetector的detect()方法
- if (!IS_ASYNC) {
- int result2 = textDetector.detect(image, text, null); // 同步
- sendResult(text.getValue());
- } else {
- int result2 = textDetector.detect(image, null, visionCallback); // 异步
- }
- }
- @Override
- public void onServiceDisconnect() {
- // 释放
- if ((!IS_ASYNC && (result == 0)) || (IS_ASYNC && (result == IS_ASYNC_CODE))) {
- textDetector.release();
- }
- if (pixelMap != null) {
- pixelMap.release();
- pixelMap = null;
- }
- VisionManager.destroy();
- }
- };
- }
- public void 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(int resId) {
- 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);
- return pixelMap;
- }
- private static byte[] readBytes(Resource resource) {
- final int bufferSize = 1024;
- final int ioEnd = -1;
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- byte[] buffers = new byte[bufferSize];
- byte[] results = new byte[0];
- while (true) {
- try {
- int readLen = 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");
- }
- }
- }
- return results;
- }
- }
复制代码- public class WordSegment {
- private static final boolean IS_ASYNC = true;
- private static final String WORDS = "words";
- private static final int ZERO = 0;
- private static final int TWO = 2;
- private static final int STEP = 8;
- private Context slice;
- private MainAbilitySlice.MyEventHandle handle;
- public void wordSegment(Context context, String requestData, MainAbilitySlice.MyEventHandle myEventHandle) {
- slice = context;
- handle = 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);
- }
- 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();
- }
- });
- }
- 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);
- }
- }
复制代码4.ability_main.xml布局文件
- <?xml version="1.0" encoding="utf-8"?>
- <DirectionalLayout
- 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"
- >
- <ListContainer
- ohos:id="$+id:picture_list_show"
- ohos:height="200vp"
- ohos:width="match_parent"
- ohos:orientation="horizontal"
- ohos:left_margin="5vp"
- ohos:right_margin="5vp"
- />
- <Text
- 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"
- />
- <TextField
- 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"/>
- <Button
- 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"/>
- <Text
- 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"
- />
- <ListContainer
- ohos:id="$+id:picture_list_match"
- ohos:height="200vp"
- ohos:width="match_parent"
- ohos:orientation="horizontal"
- ohos:left_margin="5vp"
- ohos:right_margin="5vp"
- />
- </DirectionalLayout>
复制代码5.Build代码运行显示效果如下:
`