HarmonyOS Sample 之 AI能力应用之 报菜名儿

登山则情满于山,观海则意溢于海。这篇文章主要讲述HarmonyOS Sample 之 AI能力应用之 报菜名儿相关的知识,希望能为你提供帮助。
本文正在参与优质创作者激励
@toc
HarmonyOS Sample 之 AI能力应用之 报菜名儿 1.介绍小的时候就看过一个节目,就报菜名,一直印象很深刻,“蒸羊羔、蒸熊掌、蒸鹿尾儿、烧花鸭、烧雏鸡儿、烧子鹅、卤煮咸鸭、酱鸡、腊肉、松花、小肚儿”,历历在目。
前几天,家里的小朋友在背诵校园童谣,背古诗,也得帮着儿,就想着可以结合AI能力开发一个小的应用,具备以下2个能力:
1.支持拍照,然后能提取出照片中的文字。(相机功能+通用文字提取能力)
2.能把提取的文字朗读出来,最后能通过语音进行控制。(Tts能力+Asr语音识别)
使用过程是这样的,
拍摄照片---> 预览照片----> 提取文字----> 朗读内容----> 实现语音控制菜单(可选)
2.效果展示

HarmonyOS Sample 之 AI能力应用之 报菜名儿

文章图片

3.搭建环境安装DevEco Studio,详情请参考DevEco Studio下载。
设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:
如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。
如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。
下载源码后,
使用DevEco Studio 打开项目,需要在真机上运行,参见 使用远程真机运行应用 。
4.项目结构
HarmonyOS Sample 之 AI能力应用之 报菜名儿

文章图片

HarmonyOS Sample 之 AI能力应用之 报菜名儿

文章图片

5.代码讲解 5.1 拍摄照片介绍(相机功能)
照片拍摄的界面是MainAbilitySlice.java,主要是申请权限的代码,初始化组件然后调用相机工具类实现拍摄功能。相机工具类参考了官方给的AI相机的示例代码,CameraUtil.java 提供了拍摄画面预览、拍照、切换前后摄像头、保存照片的基础功能,核心代码如下:
1.初始化相机预览画面
/** * 初始化屏幕 * * @param surfaceContainer */ public void initSurface(Component surfaceContainer) { HiLog.info(LABEL, "initSurface"); //相机屏幕 surfaceProvider = new SurfaceProvider(slice); DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig( ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT); surfaceProvider.setLayoutConfig(params); //toTop --指定是否将Surface固定在最上面,值为true表示将Surface放在AGP容器组件的顶层,false表示相反。 surfaceProvider.pinToZTop(true); surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceCallBack()); if (surfaceContainer instanceof ComponentContainer) { ((ComponentContainer) surfaceContainer).addComponent(surfaceProvider); } }

2.打开相机预览画面
private void openCamera() { HiLog.info(LABEL, "openCamera"); //图像帧数据接收处理对象 imageReceiver = ImageReceiver.create(SCREEN_WIDTH, SCREEN_HEIGHT, ImageFormat.JPEG, IMAGE_RCV_CAPACITY); //新图像接收监听 imageReceiver.setImageArrivalListener(this::saveImage); //获取相机组件实例对象 CameraKit cameraKit = CameraKit.getInstance(slice.getApplicationContext()); if (cameraKit == null) { // 处理cameraKit获取失败的情况 HiLog.error(LABEL, "CameraKit getInstance error"); }else{ //获取相机id列表 String[] cameraList = cameraKit.getCameraIds(); //获取前/后相机ID String cameraId = cameraList.length > 1 & & isCameraRear ? cameraList[1] : cameraList[0]; //相机状态回调 CameraStateCallbackImpl cameraStateCallback = new CameraStateCallbackImpl(); //创建相机 cameraKit.createCamera(cameraId, cameraStateCallback, creamEventHandler); }} /** * 相机状态回调 * CameraStateCallbackImpl * * @since 2021-03-08 */ class CameraStateCallbackImpl extends CameraStateCallback { CameraStateCallbackImpl() { }@Override public void onCreated(Camera camera) { HiLog.info(LABEL, "onCreated"); //获取预览 previewSurface = surfaceProvider.getSurfaceOps().get().getSurface(); if (previewSurface == null) { HiLog.info(LABEL, "create camera filed, preview surface is null"); return; }try { Thread.sleep(SLEEP_TIME); } catch (InterruptedException exception) { HiLog.info(LABEL, "Waiting to be interrupted"); }//提供配置相机的方法,例如添加或移除表面,以及设置相机运行模式。 CameraConfig.Builder cameraConfigBuilder = camera.getCameraConfigBuilder(); //配置预览的Surfac cameraConfigBuilder.addSurface(previewSurface); //配置拍照的Surface cameraConfigBuilder.addSurface(imageReceiver.getRecevingSurface()); //相机设备配置 camera.configure(cameraConfigBuilder.build()); cameraDevice = camera; //相机已准备好,eventId=2,设置拍照/切换摄像头按钮可用 handler.sendEvent(2); } ... } /** * 相机预览画面回调 * 提供为表面操作添加或删除回调的方法。 */ class SurfaceCallBack implements SurfaceOps.Callback { @Override public void surfaceCreated(SurfaceOps callbackSurfaceOps) { if (callbackSurfaceOps != null) { callbackSurfaceOps .setFixedSize(surfaceProvider.getHeight(), surfaceProvider.getWidth()); } openCamera(); }@Override public void surfaceChanged(SurfaceOps callbackSurfaceOps, int format, int width, int height) { }@Override public void surfaceDestroyed(SurfaceOps callbackSurfaceOps) { } }

3.实现拍照
/** * 拍照 */ public void takePicture(Component takePictureImage) { HiLog.info(LABEL, "takePicture"); if (!takePictureImage.isEnabled()) { HiLog.info(LABEL, "takePicture return"); return; } if (cameraDevice == null || imageReceiver == null) { return; }//添加一个表面作为帧捕获输出。 FrameConfig.Builder framePictureConfigBuilder = cameraDevice.getFrameConfigBuilder(FRAME_CONFIG_PICTURE); //添加图像接收Surface framePictureConfigBuilder.addSurface(imageReceiver.getRecevingSurface()); //提供用于帧捕获配置、图像处理和图像输出的方法。 FrameConfig pictureFrameConfig = framePictureConfigBuilder.build(); //开始单帧捕捉。 cameraDevice.triggerSingleCapture(pictureFrameConfig); }

4.保存照片
/** * 保存照片到存储设备 * 并复制一份到分布式文件系统 * * @param receiver */ public void saveImage(ImageReceiver receiver) { //文件起名 fileName = IMG_FILE_PREFIX + System.currentTimeMillis() + IMG_FILE_TYPE; //外部存储的文件目录 targetFile = new File(slice.getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName); try { HiLog.info(LABEL, "filePath is " + targetFile.getCanonicalPath()); } catch (IOException e) { HiLog.error(LABEL, "filePath is error"); }ohos.media.image.Image image = receiver.readNextImage(); if (image == null) { return; } ohos.media.image.Image.Component component = image.getComponent(ImageFormat.ComponentType.JPEG); bytes = new byte[component.remaining()]; component.read(bytes); try (FileOutputStream output = new FileOutputStream(targetFile)) { output.write(bytes); output.flush(); //保存参数 Map< String, Object> dataMap = new HashMap< > (); dataMap.put("fileName", fileName); dataMap.put("remaining", bytes); //发送事件 InnerEvent event = InnerEvent.get(EVENT_IMAGESAVING_PROMTING, 1, dataMap); handler.sendEvent(event); //复制图片到分布式文件系统目录 DistributeFileUtil.copyPicToDistributedDir(slice, targetFile, fileName); } catch (IOException e) { HiLog.info(LABEL, "IOException, Save image failed"); } }

5.相机底部缩略图的处理
用到了MyDrawTask.java工具类,它提供了将像素矩阵绘制到image组件的功能,同时处理了缩略图的大小等样式。
** * 绘制任务 * 绘制一个照片缩略图 * @since 2021-03-08 */ public class MyDrawTask implements Component.DrawTask { private static final HiLogLabel LABEL = new HiLogLabel(LOG_APP, 0x00204, "=> " + MyDrawTask.class.getName()); private static final int HALF = 2; private static final int STROKE_WIDTH = 3; private static final int MAX_SIZE = 66; private Component component; private PixelMap pixelMap; private RectFloat rectSrc; /** * MyDrawTask * * @param component component */ public MyDrawTask(Component component) { HiLog.info(LABEL, "MyDrawTask"); this.component = component; }/** * putPixelMap * 以像素矩阵的形式提供图像 * @param pm Provides images in forms of pixel matrices */ public void putPixelMap(PixelMap pm) { if (pm != null) { pixelMap = pm; int halfWidth = pixelMap.getImageInfo().size.width / HALF; int halfHeight = pixelMap.getImageInfo().size.height / HALF; int center = Math.min(halfWidth, halfHeight); rectSrc = https://www.songbingjia.com/android/new RectFloat(halfWidth - center, halfHeight - center, halfWidth + center, halfHeight + center); component.invalidate(); } }@Override public void onDraw(Component component1, Canvas canvas) { int halfWidth = component.getWidth() / HALF; int halfHeight = component.getHeight() / HALF; int center = Math.min(halfWidth, halfHeight); if (center > MAX_SIZE) { center = MAX_SIZE; }int radius = center - STROKE_WIDTH / HALF; if (pixelMap != null) { canvas.drawPixelMapHolderCircleShape(new PixelMapHolder(pixelMap), rectSrc, halfWidth, halfHeight, radius); }Paint roundPaint = new Paint(); roundPaint.setAntiAlias(true); roundPaint.setStyle(Paint.Style.STROKE_STYLE); roundPaint.setStrokeWidth(STROKE_WIDTH); roundPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP); roundPaint.setColor(Color.WHITE); canvas.drawCircle(halfWidth, halfHeight, radius, roundPaint); } }

工具类中使用 EventHandler对象,实现跨线程通知的目的。
以上需要ohos.permission.CAMERA和ohos.permission.WRITE_MEDIA权限。
5.2 预览照片介绍(PixelMap的使用)
预览照片的界面是ImageAbilitySlice.java 主要是读取本地存储的照片后并做显示。
/** * 本地读取照片并显示 * * @param picPath */ private void setImage(String picPath) { HiLog.info(LABEL, "setImage"); if (picPath != null & & !picPath.isEmpty()) { PixelMap pixelMap = PixelMapUtil.getPixelMapByLocalPath(null, picPath, 1); bigImage.setPixelMap(pixelMap); } }

/** * 将图片转换为PixeMap便于使用 */ public static PixelMap getPixelMapByLocalPath(byte[] imageBytes, String imagePath, int rotateCount) { ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions(); sourceOptions.formatHint = "image/jpg"; ImageSource imageSource; if (imagePath != null & & !imagePath.isEmpty()) { imageSource = ImageSource.create(imagePath, sourceOptions); } else if (imageBytes != null) { imageSource = ImageSource.create(imageBytes, sourceOptions); } else { return null; } ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions(); decodingOpts.desiredSize = new Size(0, 0); // decodingOpts.rotateDegrees = DEGREES_90 * rotateCount; decodingOpts.desiredPixelFormat = PixelFormat.ARGB_8888; return imageSource.createPixelmap(decodingOpts); }

5.3 提取文字介绍(通用文字识别能力)
WordRecognition.java //抽取了通用文字识别能力的工具类
TextDetectorAbilitySlice.java //文字识别能力页
1.init方法,传递要识别的图片路径和其他参数
/** * 设置参数方法 * * @param context页面 * @param picturePaths图片集合 * @param eventHandler MyEventHandle对象 * @since 2021-01-21 */ public void init(Context context, String[] picturePaths, EventHandler eventHandler) { slice = context; pictureLists = picturePaths; handler = eventHandler; }

2.开始文字识别
/** * 文字识别方法 * * @param picPath picPath * @since 2021-01-21 */ public void wordRecognition(String picPath) { HiLog.debug(LABEL, "wordRecognition"); photoPath = picPath; // 实例化ITextDetector接口 textDetector = VisionManager.getTextDetector(slice); // 实例化VisionImage对象image,并传入待检测图片pixelMap pixelMap = PixelMapUtil.getPixelMapByLocalPath(null, picPath, 1); VisionImage image = VisionImage.fromPixelMap(pixelMap); // 定义VisionCallback< Text> 回调,异步模式下用到 VisionCallback< Text> visionCallback = getVisionCallback(); // 定义ConnectionCallback回调,实现连接能力引擎成功与否后的操作 ConnectionCallback connectionCallback = getConnectionCallback(image, visionCallback); // 建立与能力引擎的连接 VisionManager.init(slice, connectionCallback); }

3.实现识别结果的回调函数
/** * 提供接收服务状态变化的回调方法, * 当服务状态改变时调用该接口。 * @param image * @param visionCallback * @return */ private ConnectionCallback getConnectionCallback(VisionImage image, VisionCallback< Text> visionCallback) { return new ConnectionCallback() { @Override public void onServiceConnect() { HiLog.debug(LABEL, "onServiceConnect"); //存储给定图像中文本的检测结果。 Text text = new Text(); // 通过TextConfiguration配置textDetector()方法的运行参数 TextConfiguration.Builder builder = new TextConfiguration.Builder(); //MODE_IN模式表示SDK在调用者进程中直接调用OCR函数。 //MODE_OUT模式表示SDK作为客户端向HUAWEI HiAI Engine发送调用请求,由HUAWEI HiAI Engine进行OCR并将结果返回给调用方。 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_SYNC) { HiLog.debug(LABEL, "IS_SYNC"); //result不为0,说明当前OCR能力准备失败 result = textDetector.detect(image, text, null); // 同步 HiLog.debug(LABEL, "IS_SYNC,result:" + result); // sendResult(text.getValue()); } else { HiLog.debug(LABEL, "!IS_SYNC"); //result=700:异步调用请求发送成功 result = textDetector.detect(image, null, visionCallback); // 异步 HiLog.debug(LABEL, "!IS_SYNC,result:" + result); } }@Override public void onServiceDisconnect() { HiLog.debug(LABEL, "onServiceDisconnect"); // 释放 if ((IS_SYNC & & result == 0 & & textDetector != null)) { textDetector.release(); } if (pixelMap != null) { pixelMap.release(); pixelMap = null; } //断开HUAWEI HiAI Engine服务。 VisionManager.destroy(); } }; }

4.异步模式下的回调函数
/** * 异步模式下回调 * * @return */ private VisionCallback< Text> getVisionCallback() { return new VisionCallback< Text> () { @Override public void onResult(Text text) { HiLog.debug(LABEL, "onResult"); //异步情况下返回识别结果后发送 sendResult(text.getValue()); }@Override public void onError(int index) { HiLog.debug(LABEL, "onError"); }@Override public void onProcessing(float value) { HiLog.debug(LABEL, "onProcessing"); } }; }

最后是通过EventHandler对象将识别的结果发送给TextDetectorAbilitySlice.java
进行界面展示。
5.4 朗读内容介绍(Tts能力)
Tts能力封装在TtsUtil.java工具类,核心类包括:
import ohos.ai.tts.TtsClient; // TTS客户端 import ohos.ai.tts.TtsListener; // TTS 监听接口 import ohos.ai.tts.TtsParams; // TTS参数 import ohos.ai.tts.constants.TtsEvent; // TTS事件 import ohos.utils.PacMap; // TTS依赖

1.初始化参数
/** * 初始化参数 * * @param contextSlice对象 * @param eventHandler 事件传递对象 * @since 2021-01-21 */ public void init(Context context, EventHandler eventHandler) { slice = context; handler = eventHandler; //创建Tts客户端 TtsClient.getInstance().create(slice, ttsListener); }

2.实例化事件监听
/** * 实例化TTS 事件监听 */ private TtsListener ttsListener = new TtsListener() { @Override public void onEvent(int eventType, PacMap pacMap) { HiLog.info(LABEL, "onEvent...eventType:" + eventType); // 定义TTS客户端创建成功的回调函数 if (eventType == TtsEvent.CREATE_TTS_CLIENT_SUCCESS) { TtsParams ttsParams = new TtsParams(); //必填 ttsParams.setDeviceId(UUID.randomUUID().toString()); //语速 //ttsParams.setSpeed(8); //ttsParams.setSpeaker(SPEAKER_XIAOYI); //ttsParams.setVolume(4); //Tts初始化结果 createSucc = TtsClient.getInstance().init(ttsParams); //发送初始化成功事件 sendResult(createSucc + "", 4); } }@Override public void onSpeechStart(String utteranceId) { HiLog.info(LABEL, "onSpeechStart..."); sendResult("开始朗读", 5); }@Override public void onSpeechFinish(String utteranceId) { HiLog.info(LABEL, "onSpeechFinish..."); sendResult("朗读完成", 6); }@Override public void onStart(String utteranceId) { HiLog.info(LABEL, "onStart..."); }@Override public void onProgress(String utteranceId, byte[] audioData, int progress) { }@Override public void onFinish(String utteranceId) { HiLog.info(LABEL, "onFinish..."); }@Override public void onError(String s, String s1) { HiLog.info(LABEL, "onError...s:" + s + ",s1:" + s1); }@Override public void onSpeechProgressChanged(String utteranceId, int progress) { } };

5.5 语音控制介绍(Asr能力)
自定义ASR工具类AsrUtil.java ,提供了Asr的相关功能,通过语音识别获取指定菜单指令,然后执行相应动作。Asr核心类如下:
import ohos.ai.asr.AsrIntent; // 提供ASR引擎执行时所需要传入的参数类 import ohos.ai.asr.util.AsrError; // 错误码的定义类 import ohos.ai.asr.AsrListener; // 加载语音识别Listener import ohos.ai.asr.AsrClient; // 提供调用ASR引擎服务接口的类 import ohos.ai.asr.util.AsrResultKey; // ASR回调结果中的关键字封装类

1.初始化参数
/** * 初始化参数 * * @param contextSlice对象 * @param eventHandler 事件传递对象 * @since 2021-01-21 */ public void initAsrClient(Context context, EventHandler eventHandler) { HiLog.debug(LABEL, "initAsrClient"); slice = context; handler = eventHandler; //release(); initAudioCapture(); initAsrClient(); }

2.实例化TTS 事件监听
//初始化 ASR 引擎时,调用者决定如何实现该接口。 private AsrListener asrListener = new MyAsrListener() { @Override public void onInit(PacMap params) { HiLog.debug(LABEL, "onInit"); super.onInit(params); //打开录音 if (!isAsrListener) { HiLog.debug(LABEL, "!isAsrListener"); isAsrListener = true; //新线程去处理,拾取PCM音频流交给asrClient poolExecutor.submit(new AudioCaptureRunnable()); }}@Override public void onError(int error) { super.onError(error); HiLog.error(LABEL, "error:" + (error == 6 ? "在设定的时间内没有语音输入时,在回调中会返回的结果码" : error)); }@Override public void onIntermediateResults(PacMap pacMap) { super.onIntermediateResults(pacMap); HiLog.debug(LABEL, "onIntermediateResults"); String result = pacMap.getString(AsrResultKey.RESULTS_INTERMEDIATE); //发送识别结果 sendResult(result, 6); }@Override public void onResults(PacMap results) { super.onResults(results); HiLog.debug(LABEL, "onResults"); }@Override public void onEnd() { super.onEnd(); HiLog.debug(LABEL, "onEnd"); if (!recognizeOver) { startListening(); } } }; /** * 获取 PCM 音频流并在录制过程中将它们发送到 ASR 引擎。 * * @since 2021-03-08 */ private class AudioCaptureRunnable implements Runnable { @Override public void run() { byte[] buffers = new byte[BYTES_LENGTH]; //录音开始 audioCapturer.start(); HiLog.debug(LABEL, "audioCapturer start!"); while (isAsrListener) { //读取音频输入 int ret = audioCapturer.read(buffers, 0, BYTES_LENGTH); if (ret > = 0) { //将 PCM 音频流写入字节数组并执行语音识别。 asrClient.writePcm(buffers, BYTES_LENGTH); } } } }

3.初始化录音程序
/** * 初始化录音程序 */ private void initAudioCapture() { HiLog.debug(LABEL, "initAudioCapture"); //初始化线程池 poolExecutor = new ThreadPoolExecutor( POOL_SIZE, POOL_SIZE, ALIVE_TIME, TimeUnit.SECONDS, new LinkedBlockingQueue< > (CAPACITY), new ThreadPoolExecutor.DiscardOldestPolicy()); //提供音频流信息 AudiostreamInfo audioStreamInfo = new AudioStreamInfo.Builder() .encodingFormat(AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT) .channelMask(AudioStreamInfo.ChannelMask.CHANNEL_IN_MONO) .sampleRate(SAMPLE_RATE) .build(); //提供录音所需的参数结构 AudioCapturerInfo audioCapturerInfo = new AudioCapturerInfo.Builder().audioStreamInfo(audioStreamInfo).build(); //初始化录音程序 audioCapturer = new AudioCapturer(audioCapturerInfo); }

4.初始化 ASR 引擎服务客户端
/** * 初始化 ASR 引擎服务客户端 */ private void initAsrClient() { HiLog.debug(LABEL, "initAsrClient"); //创建一个 AsrClient 实例 asrClient = AsrClient.createAsrClient(slice).orElse(null); //任务分发器 TODO TaskDispatcher taskDispatcher = slice.getMainTaskDispatcher(); taskDispatcher.asyncDispatch( () -> { if (asrClient != null) { //初始化 ASR 引擎服务。 asrClient.init(setInitIntent(), asrListener); } }); }//Asr引擎输入参数 private AsrIntent setInitIntent() { HiLog.debug(LABEL, "setInitIntent"); //提供用于执行 ASR 引擎方法的输入参数。 AsrIntent initIntent = new AsrIntent(); //识别音频流 initIntent.setAudioSourceType(AsrIntent.AsrAudioSrcType.ASR_SRC_TYPE_PCM); // initIntent.setEngineType(AsrIntent.AsrEngineType.ASR_ENGINE_TYPE_LOCAL); return initIntent; }

4.开始录音和停止语音识别
public void startListening() { HiLog.debug(LABEL, "startListening"); if (asrClient != null) { //开始阅读和识别语音数据。 asrClient.startListening(setStartIntent()); } sendResult("语音控制已开启----> ^_^~~", 6); recognizeOver = false; isAsrListener = true; }/** * 停止录音和识别 */ public void stopListening() { HiLog.debug(LABEL, "stopListening"); if (asrClient != null) { // 取消识别 asrClient.stopListening(); } //识别结束 recognizeOver = true; //isAsrListener = false; sendResult("语音控制已关闭----> @_@~~", 6); }

发送事件通知

5.6 NluAbilitySlice.java 代码
/** * 朗读文本 */ private void speakingText() { try { if (initTtsResult) { HiLog.debug(LABEL, "speakingText,text:" + inputText.getText()); stopSpeaking(); //朗读长文本,文本最大支持长度为100000,speakText最长512个字符 TtsClient.getInstance().speakLongText(inputText.getText(), null); } else { new ToastDialog(this).setText("Tts客户端初始化失败").show(); } } catch (Exception e) { HiLog.error(LABEL,"ERROR:"+e.getLocalizedMessage()); e.printStackTrace(); } }/** * 停止朗读 */ private void stopSpeaking() { TtsClient.getInstance().stopSpeak(); }

匹配语音指令
//命令关键词 private static final Map< String, Boolean> COMMAND_MAP = new HashMap< > (); static { COMMAND_MAP.put("朗读菜单", true); COMMAND_MAP.put("关闭语音控制", true); COMMAND_MAP.put("停止朗读", true); COMMAND_MAP.put("获取分词", true); COMMAND_MAP.put("词性标注", true); COMMAND_MAP.put("提取关键字", true); COMMAND_MAP.put("实体识别", true); } /** * 匹配指令 * * @param result * @return */ private void matchWords(String result) { if (result != null & & !result.isEmpty()) { if (result.indexOf({) == -1) { resultText.setText(result); } else { JSONObject jsonObject = JSONObject.parseObject(result); JSONObject resultObject = new JSONObject(); if (jsonObject.getJSONArray("result").get(0) instanceof JSONObject) { resultObject = (JSONObject) jsonObject.getJSONArray("result").get(0); } String resultWord = resultObject.getString("ori_word").replace(" ", ""); resultText.setText(resultWord); boolean command = COMMAND_MAP.getOrDefault(resultWord, false); HiLog.debug(LABEL, "command:" + command); switch (resultWord) { case "朗读菜单": HiLog.debug(LABEL, resultWord); speakingText(); break; case "停止朗读": HiLog.debug(LABEL, resultWord); stopSpeaking(); break; case "关闭语音控制": HiLog.debug(LABEL, resultWord); asrUtil.stopListening(); break; case "获取分词": HiLog.debug(LABEL, resultWord); //分词能力 String requestData = "https://www.songbingjia.com/android/{//"text\\":\\"" + inputText.getText() + "\\",\\"type\\":9223372036854775807}"; nluClientUtil.wordSegment(requestData); break; } } } }/** * 事件Handle * * @since 2021-01-15 */ public class MyEventHandler extends EventHandler { MyEventHandler(EventRunner runner) throws IllegalArgumentException { super(runner); }@Override protected void processEvent(InnerEvent event) { super.processEvent(event); //事件类型 HiLog.debug(LABEL, "processEvent,eventId:" + event.eventId); switch (event.eventId) { //分词事件 case 0: if (event.object instanceof List) { Optional< List< String> > optionalStringList = TypeUtil.castList(event.object, String.class); if (optionalStringList.isPresent() & & optionalStringList.get().size() > 0 & & (!"no keywords".equals(optionalStringList.get().get(0)))) { //获取分词结果列表 List< String> lists = optionalStringList.get(); resultText.setText(lists.toString()); } } break; //Tts初始化成功事件 case 4: Boolean success = Boolean.valueOf(event.object + ""); HiLog.debug(LABEL, "processEvent,initTtsResult:" + success); initTtsResult = success; break; case 6: String audio = String.valueOf(event.object); //HiLog.debug(LABEL, "processEvent,audio:" + audio); //匹配命令 matchWords(audio); break; default: HiLog.debug(LABEL, "processEvent,String:"); String res = String.valueOf(event.object); HiLog.debug(LABEL, "processEvent,res:" + res); resultText.setText(res); break; } } }

6.完整代码https://harmonyos.51cto.com/resource/1539
想了解更多关于鸿蒙的内容,请访问:
51CTO和华为官方战略合作共建的鸿蒙技术社区
https://harmonyos.51cto.com/#bkwz
::: hljs-center
HarmonyOS Sample 之 AI能力应用之 报菜名儿

文章图片

【HarmonyOS Sample 之 AI能力应用之 报菜名儿】:::

    推荐阅读