
回复
在华为云的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);
}
2.从缓存区读取文件,并压缩
/**
* 读取文件内容(压缩后)
* @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:ArrayBuffer=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;
}
3.构建请求体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;
}
4.解析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;
}
5.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:Uint8Array =new Uint8Array(await this.readFileContent(cacheFilePath));
// 构建请求体body
let boundary:string='-------' + (await systemDateTime.getCurrentTime(true)).toString();
let bodyContent=this.buildBodyContent(boundary,fileName,fileContent);
console.debug('请求体是:' +bodyContent);
// 记得替换你自己的接口地址
let url:string='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组件中显示。
下一篇:实现“保存到我的诊断记录”功能