[文章]【AI文字识别】jack_606 Codelab记录帖

阅读量0
0
1
`目标:鸿蒙上实现AI文字识别
1.核心MainAbilitySlice类文件如下:
  1. public class MainAbilitySlice extends AbilitySlice {
  2.     private static final int LIST_CONTAINER_ID_SHOW = ResourceTable.Id_picture_list_show;
  3.     private static final int LIST_CONTAINER_ID_MATCH = ResourceTable.Id_picture_list_match;
  4.     private static final int NEG_ONE = -1;
  5.     private static final int ZERO = 0;
  6.     private static final int ONE = 1;
  7.     private static final int TWO = 2;
  8.     private Context slice;
  9.     private EventRunner runner;
  10.     private MyEventHandle myEventHandle;
  11.     private int[] pictureLists = new int[]{ResourceTable.Media_icon_1, ResourceTable.Media_icon_2};
  12.     private Component selectComponent;
  13.     private int selectPosition;
  14.     private Button button;
  15.     private TextField textField;
  16.     private Map<Integer, String> imageInfos;
  17.     private int[] matchPictures;

  18.     @Override
  19.     public void onStart(Intent intent) {
  20.         super.onStart(intent);
  21.         super.setUIContent(ResourceTable.Layout_ability_main);

  22.         slice = MainAbilitySlice.this;

  23.         // 展示图片列表
  24.         setSelectPicture(pictureLists, LIST_CONTAINER_ID_SHOW);

  25.         // 所有图片通用文字识别
  26.         wordRecognition();

  27.         // 设置需要分词的语句
  28.         Component componentText = findComponentById(ResourceTable.Id_word_seg_text);
  29.         if (componentText instanceof TextField) {
  30.             textField = (TextField) componentText;
  31.         }

  32.         // 点击按钮进行文字识别
  33.         Component componentSearch = findComponentById(ResourceTable.Id_button_search);
  34.         if (componentSearch instanceof Button) {
  35.             button = (Button) componentSearch;
  36.             button.setClickedListener(listener -> wordSegment());
  37.         }
  38.     }

  39.     @Override
  40.     public void onActive() {
  41.         super.onActive();
  42.     }

  43.     @Override
  44.     public void onForeground(Intent intent) {
  45.         super.onForeground(intent);
  46.     }

  47.     // 设置图片选择区域
  48.     private void setSelectPicture(int[] pictures, int id) {
  49.         // 获取图片
  50.         PictureProvider newsTypeAdapter = new PictureProvider(pictures, this);

  51.         Component componentById = findComponentById(id);
  52.         if (componentById instanceof ListContainer) {
  53.             ListContainer listContainer = (ListContainer) componentById;
  54.             listContainer.setItemProvider(newsTypeAdapter);
  55.         }
  56.     }

  57.     // 通用文字识别
  58.     private void wordRecognition() {
  59.         initHandler();
  60.         WordRecognition wordRecognition = new WordRecognition();
  61.         wordRecognition.setParams(slice, pictureLists, myEventHandle);
  62.         wordRecognition.sendResult(null);
  63.     }

  64.     // 分词
  65.     private void wordSegment() {
  66.         // 组装关键词,作为分词对象
  67.         String requestData = "{"text":" + textField.getText() + ","type":0}";
  68.         initHandler();
  69.         new WordSegment().wordSegment(slice, requestData, myEventHandle);
  70.     }

  71.     // 匹配图片
  72.     private void matchImage(List<String> list) {
  73.         Set<Integer> matchSets = new HashSet<>();
  74.         for (String str: list) {
  75.             for (Integer key : imageInfos.keySet()) {
  76.                 if (imageInfos.get(key).indexOf(str) != NEG_ONE) {
  77.                     matchSets.add(key);
  78.                 }
  79.             }
  80.         }
  81.         // 获得匹配的图片
  82.         matchPictures = new int[matchSets.size()];
  83.         int i = 0;
  84.         for (int match: matchSets) {
  85.             matchPictures[i] = match;
  86.             i++;
  87.         }
  88.         // 展示图片
  89.         setSelectPicture(matchPictures, LIST_CONTAINER_ID_MATCH);
  90.     }

  91.     private void initHandler() {
  92.         runner = EventRunner.getMainEventRunner();
  93.         if (runner == null) {
  94.             return;
  95.         }
  96.         myEventHandle = new MyEventHandle(runner);
  97.     }

  98.     public class MyEventHandle extends EventHandler {
  99.         MyEventHandle(EventRunner runner) throws IllegalArgumentException {
  100.             super(runner);
  101.         }

  102.         @Override
  103.         protected void processEvent(InnerEvent event) {
  104.             super.processEvent(event);
  105.             int eventId = event.eventId;
  106.             if (eventId == ONE) {
  107.                 // 通用文字识别
  108.                 if (event.object instanceof Map) {
  109.                     imageInfos = (Map) event.object;
  110.                 }
  111.             }
  112.             if (eventId == TWO) {
  113.                 // 分词
  114.                 if (event.object instanceof List) {
  115.                     List<String> lists = (List) event.object;
  116.                     if ((lists.size() > ZERO) && (!"no keywords".equals(lists.get(ZERO)))) {
  117.                         // 根据输入关键词 匹配图片
  118.                         matchImage(lists);
  119.                     }
  120.                 }
  121.             }
  122.         }
  123.     }
  124. }
复制代码
2.PictureProvider.class文件
  1. public class PictureProvider extends BaseItemProvider {
  2.     private int[] pictureLists;
  3.     private Context context;

  4.     /**
  5.      *  picture provider
  6.      *
  7.      * [url=home.php?mod=space&uid=3142012]@param[/url] pictureLists pictureLists
  8.      * @param context context
  9.      */
  10.     public PictureProvider(int[] pictureLists, Context context) {
  11.         this.pictureLists = pictureLists;
  12.         this.context = context;
  13.     }

  14.     @Override
  15.     public int getCount() {
  16.         return pictureLists == null ? 0 : pictureLists.length;
  17.     }

  18.     @Override
  19.     public Object getItem(int position) {
  20.         return Optional.of(this.pictureLists[position]);
  21.     }

  22.     @Override
  23.     public long getItemId(int position) {
  24.         return position;
  25.     }

  26.     @Override
  27.     public Component getComponent(int var1, Component var2, ComponentContainer var3) {
  28.         ViewHolder viewHolder = null;
  29.         Component component = var2;
  30.         if (component == null) {
  31.             component = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_item_image_layout,

  32.                 null, false);
  33.             viewHolder = new ViewHolder();
  34.             Component componentImage = component.findComponentById(ResourceTable.Id_select_picture_list);
  35.             if (componentImage instanceof Image) {
  36.                 viewHolder.image = (Image) componentImage;
  37.             }
  38.             component.setTag(viewHolder);
  39.         } else {
  40.             if (component.getTag() instanceof ViewHolder) {
  41.                 viewHolder = (ViewHolder) component.getTag();
  42.             }
  43.         }
  44.         if (viewHolder != null) {
  45.             viewHolder.image.setPixelMap(pictureLists[var1]);
  46.         }
  47.         return component;
  48.     }

  49.     private static class ViewHolder {
  50.         Image image;
  51.     }
  52. }
复制代码
3.WordRecognition类文件和WordSegment类文件
  1. public class WordRecognition {
  2.     private static final boolean IS_ASYNC = false;
  3.     private static final int IS_ASYNC_CODE = 700;
  4.     private Context slice;
  5.     private ITextDetector textDetector;
  6.     private PixelMap pixelMap;
  7.     private MainAbilitySlice.MyEventHandle handle;

  8.     private int[] pictureLists;
  9.     private int mediaId;
  10.     private Map maps = new HashMap<>();
  11.     private int index;
  12.     private int result;

  13.     public void setParams(Context context, int[] pictureIds, MainAbilitySlice.MyEventHandle myEventHandle) {
  14.         slice = context;
  15.         pictureLists = pictureIds;
  16.         handle = myEventHandle;
  17.     }

  18.     public void wordRecognition(Context context, int resId, MainAbilitySlice.MyEventHandle myEventHandle) {
  19.         mediaId = resId;
  20.         // 实例化ITextDetector接口
  21.         textDetector = VisionManager.getTextDetector(context);

  22.         // 实例化VisionImage对象image,并传入待检测图片pixelMap
  23.         pixelMap = getPixelMap(resId);
  24.         VisionImage image = VisionImage.fromPixelMap(pixelMap);

  25.         // 定义VisionCallback<Text>回调,异步模式下用到
  26.         VisionCallback<Text> visionCallback = getVisionCallback();

  27.         // 定义ConnectionCallback回调,实现连接能力引擎成功与否后的操作
  28.         ConnectionCallback connectionCallback = getConnectionCallback(image, visionCallback);

  29.         // 建立与能力引擎的连接
  30.         VisionManager.init(context, connectionCallback);
  31.     }

  32.     private VisionCallback getVisionCallback() {
  33.         return new VisionCallback<Text>() {
  34.             @Override
  35.             public void onResult(Text text) {
  36.                 sendResult(text.getValue());
  37.             }

  38.             @Override
  39.             public void onError(int i) {
  40.             }

  41.             @Override
  42.             public void onProcessing(float v) {
  43.             }
  44.         };
  45.     }

  46.     private ConnectionCallback getConnectionCallback(VisionImage image, VisionCallback<Text> visionCallback) {
  47.         return new ConnectionCallback() {
  48.             @Override
  49.             public void onServiceConnect() {
  50.                 // 实例化Text对象text
  51.                 Text text = new Text();

  52.                 // 通过TextConfiguration配置textDetector()方法的运行参数
  53.                 TextConfiguration.Builder builder = new TextConfiguration.Builder();
  54.                 builder.setProcessMode(VisionConfiguration.MODE_IN);
  55.                 builder.setDetectType(TextDetectType.TYPE_TEXT_DETECT_FOCUS_SHOOT);
  56.                 builder.setLanguage(TextConfiguration.AUTO);
  57.                 TextConfiguration config = builder.build();
  58.                 textDetector.setVisionConfiguration(config);
  59.                 // 调用ITextDetector的detect()方法
  60.                 if (!IS_ASYNC) {
  61.                     int result2 = textDetector.detect(image, text, null); // 同步
  62.                     sendResult(text.getValue());
  63.                 } else {
  64.                     int result2 = textDetector.detect(image, null, visionCallback); // 异步
  65.                 }
  66.             }

  67.             @Override
  68.             public void onServiceDisconnect() {
  69.                 // 释放
  70.                 if ((!IS_ASYNC && (result == 0)) || (IS_ASYNC && (result == IS_ASYNC_CODE))) {
  71.                     textDetector.release();
  72.                 }
  73.                 if (pixelMap != null) {
  74.                     pixelMap.release();
  75.                     pixelMap = null;
  76.                 }
  77.                 VisionManager.destroy();
  78.             }
  79.         };
  80.     }

  81.     public void sendResult(String value) {
  82.         if (textDetector != null) {
  83.             textDetector.release();
  84.         }
  85.         if (pixelMap != null) {
  86.             pixelMap.release();
  87.             pixelMap = null;
  88.             VisionManager.destroy();
  89.         }
  90.         if (value != null) {
  91.             maps.put(mediaId, value);
  92.         }
  93.         if ((maps != null) && (maps.size() == pictureLists.length)) {
  94.             InnerEvent event = InnerEvent.get(1, 0, maps);
  95.             handle.sendEvent(event);
  96.         } else {
  97.             wordRecognition(slice, pictureLists[index], handle);
  98.             index++;
  99.         }
  100.     }

  101.     // 获取图片
  102.     private PixelMap getPixelMap(int resId) {
  103.         ResourceManager manager = slice.getResourceManager();

  104.         byte[] datas = new byte[0];
  105.         try {
  106.             Resource resource = manager.getResource(resId);
  107.             datas = readBytes(resource);
  108.             resource.close();
  109.         } catch (IOException | NotExistException e) {
  110.             LogUtil.error("get pixelmap failed, read resource bytes failed, ", e.getLocalizedMessage());
  111.         }

  112.         ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
  113.         srcOpts.formatHint = "image/jpg";
  114.         ImageSource imageSource;
  115.         imageSource = ImageSource.create(datas, srcOpts);
  116.         ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
  117.         decodingOpts.desiredSize = new Size(0, 0);
  118.         decodingOpts.desiredRegion = new Rect(0, 0, 0, 0);
  119.         decodingOpts.desiredPixelFormat = PixelFormat.ARGB_8888;
  120.         pixelMap = imageSource.createPixelmap(decodingOpts);
  121.         return pixelMap;
  122.     }

  123.     private static byte[] readBytes(Resource resource) {
  124.         final int bufferSize = 1024;
  125.         final int ioEnd = -1;

  126.         ByteArrayOutputStream output = new ByteArrayOutputStream();
  127.         byte[] buffers = new byte[bufferSize];
  128.         byte[] results = new byte[0];
  129.         while (true) {
  130.             try {
  131.                 int readLen = resource.read(buffers, 0, bufferSize);
  132.                 if (readLen == ioEnd) {
  133.                     results = output.toByteArray();
  134.                     break;
  135.                 }
  136.                 output.write(buffers, 0, readLen);
  137.             } catch (IOException e) {
  138.                 LogUtil.error("OrcAbilitySlice.getPixelMap", "read resource failed ");
  139.                 break;
  140.             } finally {
  141.                 try {
  142.                     output.close();
  143.                 } catch (IOException e) {
  144.                     LogUtil.error("OrcAbilitySlice.getPixelMap", "close output failed");
  145.                 }
  146.             }
  147.         }
  148.         return results;
  149.     }
  150. }
复制代码
  1. public class WordSegment {
  2.     private static final boolean IS_ASYNC = true;
  3.     private static final String WORDS = "words";
  4.     private static final int ZERO = 0;
  5.     private static final int TWO = 2;
  6.     private static final int STEP = 8;
  7.     private Context slice;
  8.     private MainAbilitySlice.MyEventHandle handle;


  9.     public void wordSegment(Context context, String requestData, MainAbilitySlice.MyEventHandle myEventHandle) {
  10.         slice = context;
  11.         handle = myEventHandle;

  12.         // 使用NluClient静态类进行初始化,通过异步方式获取服务的连接。
  13.         NluClient.getInstance().init(context, new OnResultListener<Integer>() {
  14.             @Override
  15.             public void onResult(Integer resultCode) {
  16.                 if (!IS_ASYNC) {
  17.                     // 同步
  18.                     ResponseResult responseResult = NluClient.getInstance().getWordSegment(requestData,
  19.                         NluRequestType.REQUEST_TYPE_LOCAL);
  20.                     sendResult(responseResult.getResponseResult());
  21.                     release();
  22.                 } else {
  23.                     // 异步
  24.                     wordSegmentAsync(requestData);
  25.                 }
  26.             }
  27.         }, true);
  28.     }

  29.     private void wordSegmentAsync(String requestData) {
  30.         ResponseResult responseResult = NluClient.getInstance().getWordSegment(requestData,
  31.             NluRequestType.REQUEST_TYPE_LOCAL, new OnResultListener<ResponseResult>() {
  32.                 @Override
  33.                 public void onResult(ResponseResult asyncResult) {
  34.                     sendResult(asyncResult.getResponseResult());
  35.                     release();
  36.                 }
  37.             });
  38.     }

  39.     private void sendResult(String result) {
  40.         List lists = null; // 分词识别结果
  41.         // 将result中分词结果转换成list
  42.         if (result.contains(""message":"success"")) {
  43.             String words = result.substring(result.indexOf(WORDS) + STEP,
  44.                 result.lastIndexOf("]")).replaceAll(""", "");
  45.             if ((words == null) || ("".equals(words))) {
  46.                 lists = new ArrayList(1);
  47.                 lists.add("no keywords"); // 未识别到分词结果,返回"no keywords"
  48.             } else {
  49.                 lists = Arrays.asList(words.split(","));
  50.             }
  51.         }

  52.         InnerEvent event = InnerEvent.get(TWO, ZERO, lists);
  53.         handle.sendEvent(event);
  54.     }

  55.     private void release() {
  56.         NluClient.getInstance().destroy(slice);
  57.     }
  58. }
复制代码
4.ability_main.xml布局文件
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <DirectionalLayout
  3.     xmlns:ohos="http://schemas.huawei.com/res/ohos"
  4.     ohos:height="match_parent"
  5.     ohos:width="match_parent"
  6.     ohos:orientation="vertical"
  7.     ohos:background_element="$graphic:background_ability_page"
  8.     >

  9.     <ListContainer
  10.         ohos:id="$+id:picture_list_show"
  11.         ohos:height="200vp"
  12.         ohos:width="match_parent"
  13.         ohos:orientation="horizontal"
  14.         ohos:left_margin="5vp"
  15.         ohos:right_margin="5vp"
  16.         />

  17.     <Text
  18.         ohos:id="$+id:word_seg_title"
  19.         ohos:height="match_content"
  20.         ohos:width="match_content"
  21.         ohos:background_element="$graphic:background_ability_main"
  22.         ohos:left_margin="5vp"
  23.         ohos:text="请输入关键词:"
  24.         ohos:text_size="25fp"
  25.         ohos:top_margin="10vp"
  26.         />

  27.     <TextField
  28.         ohos:id="$+id:word_seg_text"
  29.         ohos:height="match_content"
  30.         ohos:width="match_parent"
  31.         ohos:background_element="$graphic:background_ability_main"
  32.         ohos:hint="Enter a statement."
  33.         ohos:left_padding="5vp"
  34.         ohos:right_padding="5vp"
  35.         ohos:text_alignment="vertical_center"
  36.         ohos:text_size="20fp"
  37.         ohos:top_margin="5vp"/>

  38.     <Button
  39.         ohos:id="$+id:button_search"
  40.         ohos:width="match_content"
  41.         ohos:height="match_content"
  42.         ohos:text_size="20fp"
  43.         ohos:text="开始通用文字识别"
  44.         ohos:layout_alignment="horizontal_center"
  45.         ohos:top_margin="10vp"
  46.         ohos:top_padding="1vp"
  47.         ohos:bottom_padding="1vp"
  48.         ohos:right_padding="20vp"
  49.         ohos:left_padding="20vp"
  50.         ohos:text_color="white"
  51.         ohos:background_element="$graphic:button_element"
  52.         ohos:center_in_parent="true"
  53.         ohos:align_parent_bottom="true"
  54.         ohos:bottom_margin="5vp"/>

  55.     <Text
  56.         ohos:id="$+id:picture_list_result"
  57.         ohos:height="match_content"
  58.         ohos:width="match_content"
  59.         ohos:background_element="$graphic:background_ability_main"
  60.         ohos:layout_alignment="horizontal_center"
  61.         ohos:text="搜索结果"
  62.         ohos:text_size="20fp"
  63.         ohos:top_margin="5vp"
  64.         />

  65.     <ListContainer
  66.         ohos:id="$+id:picture_list_match"
  67.         ohos:height="200vp"
  68.         ohos:width="match_parent"
  69.         ohos:orientation="horizontal"
  70.         ohos:left_margin="5vp"
  71.         ohos:right_margin="5vp"
  72.         />
  73. </DirectionalLayout>
复制代码
5.Build代码运行显示效果如下:

`
screenshot_20210414153956331.png

回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友