HarmonyOS鸿蒙NEXT中病虫害AI诊断预测功能实现

HarmonyOS鸿蒙NEXT中病虫害AI诊断预测功能实现

在华为云的AI ModelArts平台已部署图像分类模型的在线服务,且平台提供了在线服务的公网API。

打开PestInfoPage.ets文件,在PestDiagnosisView组件内,

  1. 定义复制文件的方法,将拍照或相册选取的图片复制到APP当前运行的缓存区
/**
 * 复制文件
 * @param from
 * @param to
 */
copyFile(from:string,to:string):void{
  let fFile=fileIo.openSync(from);
  let tFile=fileIo.openSync(to,fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE); // 替换或创建
  fileIo.copyFileSync(fFile.fd,tFile.fd);
  fileIo.closeSync(fFile);
  fileIo.closeSync(tFile);
}
  1. 从缓存区读取文件,并压缩
/**
 * 读取文件内容(压缩后)
 * @param cacheImgUri
 * @returns
 */
async readFileContent(cacheImgUri :string):Promise<ArrayBuffer>{
  let fFile=fileIo.openSync(cacheImgUri,fileIo.OpenMode.READ_ONLY);
  let fStat=fileIo.lstatSync(cacheImgUri);
  let arrayBufFile:new ArrayBuffer(fStat.size); // 压缩前文件大小
  let imgPacker=image.createImagePacker();
  let imgSource=image.createImageSource(fFile.fd);
  await imgPacker.packing(imgSource,{format:'image/jpeg',quality:40})
    .then((data:ArrayBuffer) => {
      arrayBufFile=data;
    })
    .catch((err:BusinessError) => {

    })
  return arrayBufFile;
}
  1. 构建请求体body,含需要上传的图片文件内容
/**
 * 构建请求体
 * @param boundary
 * @param fileName
 * @param fileContent
 * @returns
 */
buildBodyContent(boundary:string,fileName:string,fileContent:Uint8Array):ArrayBuffer{
  // 构建请求体前面内容
  let bodyPre=`--${boundary}\r\n`;
  bodyPre =bodyPre + `Content-Disposition: form-data; name="images"; filename="${fileName}"\r\n`;
  bodyPre =bodyPre + 'Content-Type: application/octet-stream\r\n';
  bodyPre =bodyPre + `\r\n`;
  let txtEncoder=new util.TextEncoder();
  let arrayPre=txtEncoder.encodeInto(bodyPre);

  // 构建请求体后面内容
  let bodyAft='\r\n';
  bodyAft =bodyAft + `--${boundary}`;
  bodyAft=bodyAft + '--\r\n';
  let arrayAft=txtEncoder.encode(bodyAft);

  let body=buffer.concat([arrayPre,fileContent,arrayAft]) // 构建完整请求体
  return body.buffer;
}
  1. 解析AI在线服务接口返回的JSON数据
{
  "predicted_label": "c_3", 
  "scores": [["c_3", "1.000"], ["c_24", "0.000"], ["c_25", "0.000"], ["c_26", "0.000"], ["c_27", "0.000"]]
}

并通过key值找到其对应的置信度value值

/**
 * 根据key查找value
 * @param key
 * @param dataArray
 * @returns
 */
findValueByKey(key:string,dataArray:string[][]){
  const value=dataArray.find(item => item[0] === key)?.[1];
  return value;
}
  1. AI诊断预测按钮click完整代码如下
/**
 * 调用AI模型接口
 * @param imgUri
 * @returns
 */
async aiAnalyseImg(imgUri:string):Promise<void>{
  // 文件名
  let fileName=imgUri.split('/').pop() as string;
  let cacheFilePath=`${getContext().cacheDir}/${fileName}`;
  // 复制图片
  this.copyFile(imgUri,cacheFilePath);
  // 从缓存文件读取图片数据
  let fileContent:new Uint8Array(await this.readFileContent(cacheFilePath));
  // 构建请求体body
  let boundary:'-------'+(await systemDateTime.getCurrentTime(true)).toString();
  let bodyContent=this.buildBodyContent(boundary,fileName,fileContent);
  console.debug('请求体是:'+bodyContent);
  // 记得替换你自己的接口地址
  let url:'https://b07b6d6054d241dc8776d5e44203f97e.apig.cn-north-4.huaweicloudapis.com/v1/infers/c9149048-c678-4e73-9dd4-37c01808683b';
  let request=http.createHttp();
  let reqOpts:http.HttpRequestOptions={
    // 请求头
    method:http.RequestMethod.POST,
    header:{
      'X-Apig-AppCode':'7990c0e44c5d422ab7cb5c42a0b23831f62eccb25cc34ee7b450d17445f1c630', // 记得替换你自己的APP Code
      'Content-Type`: `multipart/form-data; boundary=${boundary}`,
      'Content-Length':bodyContent.byteLength.toString()
    },
    extraData:bodyContent,
  };
  let model:PestModel | undefined;
  // 发起请求
  request.request(url,reqOpts)
    .then((resp) => {
      console.debug('请求结果是:'+resp.result);
      let aiModel=JSON.parse(resp.result.toString()) as AiPestModel;
      let label=aiModel.predicted_label??'';
      let scores=aiModel.scores??[];
      let code=aiModel.error_code??'';
      let msg=aiModel.error_msg??'';
      if (code !='') {
        AlertDialog.show({
          title:'服务异常~',
          message:'AI诊断预测服务不可用,请稍后再试。'
        });
      } else {
        let value=this.findValueByKey(label,scores)??0; // AI预测结果的置信度
        let pest: PestModel[]=LIST_PEST_DATA.filter(PestModel => PestModel.PredictedLabel === label);
        if(value<0.9 || pest==undefined || pest.length==0){
          AlertDialog.show({
            title:'诊断结果',
            message:'未发现病虫害,仅供参考。',
            cancel:() =>{
              // 关闭对话框
            }
          });
        } else {
          model=pest[0];
          this.pestObj!.PestName=model.PestName;
          this.pestObj!.Type=model.Type;
          this.pestObj!.ID=model.ID;
          this.pestObj!.PestCtrl=model.PestCtrl;
        }

      }
    })
    .catch((err:BusinessError) => {
      AlertDialog.show({
        title:'网络异常~',
        message:err.message
      });
      console.error('网络异常:'+ err.message);
    })
}

AI诊断预测成功后,解析完接口返回的数据并在PestInfoView组件中显示。

下一篇:实现“保存到我的诊断记录”功能


更多关于HarmonyOS鸿蒙NEXT中病虫害AI诊断预测功能实现的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

HarmonyOS NEXT中实现病虫害AI诊断预测功能主要涉及以下技术点:

  1. 使用ArkTS开发AI推理模块,调用NPU加速
  2. 集成华为HiAI Foundation的模型部署能力
  3. 采用MindSpore Lite框架部署预训练的图像识别模型
  4. 基于分布式能力实现端云协同推理
  5. 利用鸿蒙的Sensor API获取作物环境数据辅助诊断

数据流程:通过相机获取作物图像,经AI模型分析后返回病虫害类型及概率,结合环境传感器数据提升准确率。需准备标注好的病虫害数据集训练专用模型。

更多关于HarmonyOS鸿蒙NEXT中病虫害AI诊断预测功能实现的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


您的代码实现已经比较完整地展示了HarmonyOS中调用AI模型服务进行病虫害诊断的流程。以下是几点技术要点分析:

  1. 文件处理部分:
  • 使用了fileIo模块的openSync/copyFileSync进行文件操作
  • 通过image.createImagePacker()实现了图片压缩,建议quality参数(40)可根据实际需求调整
  1. 网络请求部分:
  • 正确构建了multipart/form-data格式的请求体
  • 使用了http.createHttp()进行API调用
  • 边界字符串boundary的生成方式可以优化为更标准的UUID
  1. 性能优化建议:
  • 可考虑添加图片尺寸检查,避免上传过大图片
  • 可添加请求超时设置(默认60秒可能过长)
  • 建议对ArrayBuffer操作添加try-catch异常处理
  1. 业务逻辑部分:
  • 置信度阈值0.9的设置合理
  • 错误处理机制完善,区分了服务异常和网络异常

整体实现符合HarmonyOS应用开发规范,代码结构清晰。后续可考虑添加本地缓存机制,在无网络时显示历史诊断记录。

回到顶部