AI 宠物面板开发模版与流程(二)

AI 宠物面板开发模版与流程(一) 

7. 宠物特征分析

  • 首先使用 App 端侧 AI 能力 对宠物图像进行宠物识别和异物过滤,完成上传图像质量判断
    • 1. 宠物图像资源导入
      • 调用 chooseImage 方法,支持用户从本地相册选择图片或使用相机拍照。
      • 调用 resizeImage 方法,保持原图长宽比裁剪至目标尺寸,再根据文件大小限制进行质量压缩。
    • 2. 宠物图像质量检测
      • 调用 petsDetectCreate 方法,初始化 AI 宠物图像质量检测实例。
      • 调用 petsPictureQualityDetectForImage 方法,输入参数进行质量检测并返回结果。
      • 页面销毁时调用 petsDetectDestory 方法销毁实例,避免内存泄漏。
  • 若图像通过 端侧 AI 质量判定,则上传至云端分析宠物体型、毛色、表情等特征,实现进食时的精准识别
    • 1. 请求云端获取文件上传签名及对应 objectKey
    • 2. 图片上传与分析流程
      • 将图片上传至指定服务器,完成后传递 objectKey 至特征分析接口。
      • 接口返回 taskId,通过轮询获取分析进度:
        • 若 analysisResult 为 2,表示分析成功。
        • 若 analysisResult 为 1,表示分析失败。

功能展示

相关代码段

export async function pictureQualityDetect(pathUrl: string) {
  const result = await new Promise<{
    imagePath: string;
    lowQuality: boolean;
    lowQualityReason: number;
  }>((resolve, reject) => {
    petsPictureQualityDetectForImage({
      inputImagePath: pathUrl,
      labelAllow: 1,
      objectAreaPercent: 30,
      objectFaceRotationAngle: 40,
      objectFaceSideAngle: 45,
      maximumPictureBrightness: 80,
      minimumPictureBrightness: 0,
      success: res => {
        resolve(res);
      },
      fail: error => {
        reject(error);
      },
    });
  });

  return result;
}

  const handleChooseImg = async () => {
    let paths = [];

    try {
      // paths = await chooseImage(3);
      paths = await chooseImage(3, () => enter('analyzing'));
    } catch (err) {
      return;
    }

    // 先进入下一阶段
    // enter('analyzing');

    setState({
      analyzingText: Strings.getLang('add_pet_analytics_upload_img'),
    });

    const controller = new AbortController();
    controllerRef.current = controller;
    let tempPaths: Array<{ imagePath: string; lowQuality: boolean; lowQualityReason: number }> = [];
    let pathList: Array<{ imagePath: string; lowQuality: boolean; lowQualityReason: number }> = [];

    if (petType === 'cat') {
      try {
        tempPaths = (await Promise.all(paths.map(url => pictureQualityDetect(url)))).map(d => d);

        pathList = tempPaths.filter(item => !item.lowQuality) as Array<{
          imagePath: string;
          lowQuality: boolean;
          lowQualityReason: number;
        }>;
        const lowQualityList = tempPaths
          .filter(item => item.lowQuality)
          .map(item => item.lowQualityReason) as Array<number>;

        if (pathList.length === 0) {
          const errorText = Array.from(new Set(lowQualityList)).map((lowQualityItem, index) => {
            return `${Strings.getLang(`dsc_${lowQualityItem}`)}`;
          });
          setPicErrorTips(errorText.join('、'));
          setTimeout(() => {
            enter('failed');
          }, 1000);

          return;
        }
      } catch (error) {
        enter('failed');
        return;
      }
    }

    let images: Array<{ imageDisplayUrl: string; objectKey: string }> = [];

    const pathSourceList = petType === 'cat' ? pathList.map(element => element.imagePath) : paths;
    try {
      images = (
        await Promise.all(pathSourceList.map(p => uploadImageCat(p, ANALYTICS_BIZ_TYPE)))
      ).map(d => ({
        imageDisplayUrl: d.publicUrl,
        objectKey: d.cloudKey,
      }));
      if (controller.signal.aborted) {
        return;
      }
    } catch (error) {
      setTimeout(() => {
        enter('failed');
      }, 1000);
      return;
    }

    let idx = 0;
    const tips = [
      Strings.getLang('add_pet_analytics_upload_tip1'),
      Strings.getLang('add_pet_analytics_upload_tip2'),
      Strings.getLang('add_pet_analytics_upload_tip3'),
      Strings.getLang('add_pet_analytics_upload_tip4'),
      Strings.getLang('add_pet_analytics_upload_tip5'),
    ];

    const id = setInterval(() => {
      setState({
        analyzingText: tips[idx++ % tips.length],
      });
    }, 3000);

    try {
      const taskId = await analyzePetFeature({
        ownerId: homeId,
        images,
        miniAppId,
        agentId: AGENT_ID,
      });
      const [infoRes] = await Promise.all([
        loopGetAnalysisResult({
          taskId,
          controller,
          type: AnalysType.Profile,
        }),
      ]);
      if (infoRes) {
        setState({
          similarShow: true,
          petResInfo: infoRes,
        });
      } else if (infoRes) {
        emitter.emit('selectProfile', infoRes);
        enter('success');
      } else {
        // 超时
        enter('failed');
      }
    } catch (error) {
      enter('failed');
      return;
    } finally {
      clearInterval(id);
    }
  };

// 上传图片
export async function uploadImage(filePath: string, bizType: UploadFileBizType) {
  const fileName = parseFileName(filePath);
  const signInfo = await getPetUploadSign({ bizType, fileName });
  const { url, objectKey } = signInfo;

  await uploadFile(url, filePath, fileName);

  return { cloudKey: objectKey };
}

8. 多宠识别记录

主要展示家庭下宠物进食情况,当宠物来进食时,会识别出具体哪只宠物,并生成一条进食记录。

相关代码段

const [eatingRecords, setEatingRecords] = useState<IEatingRecord[]>([]);

const getData = async (pageNo: number, isFresh?: boolean) => {
  try {
    const day = dayjs();
    const startOfDay = day.clone().startOf('day').valueOf();
    const endOfDay = day.clone().endOf('day').valueOf();
    setRefreshing(!!isFresh);

    const eatParams = {
      ownerId: homeId,
      uuid: getDevInfo().uuid,
      startTime: startOfDay,
      endTime: endOfDay,
      pageNo,
      pageSize: 100,
    };
    const { pageNo: pageNumber, hasNext, data = [] } = await fetchPetEatingRecordApi(eatParams);
    setRefreshing(false);
    setHasNext(hasNext);
    setCurrentPageNo(pageNumber);

    const formattedEatingRecord = data.map(item => {
      const petName = Array.isArray(item.pets)
        ? item.pets.map(p => {
            return find(pets, { id: p.petId })?.name;
          })
        : Strings.getLang('pet');
      return {
        ...item,
        timeStamp: item.recordTime,
        type: RECORD_DATA_TYPE.feed,
        desc: Strings.formatValue('dsc_feed_eating', petName),
      };
    });

    if (pageNo > 1) {
      setEatingRecords([...eatingRecords, ...formattedEatingRecord]);
    } else {
      setEatingRecords(formattedEatingRecord);
    }
  } catch (error) {
    setRefreshing(false);
    console.log('fetch error: ', error);
  }
};

AI 宠物面板开发模版与流程(三)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IoT砖家涂拉拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值