前提条件

开发环境

详见 面板小程序 > 搭建环境

功能拆分

开发者平台创建面板小程序

面板小程序的开发在 小程序开发者 平台上进行操作,首先请前往 小程序开发者平台 完成平台的注册登录。

详细操作步骤,请参考 创建面板小程序

IDE 基于示例模板创建项目工程

登录 Tuya MiniApp IDE,创建一个基于 AI 图像增强功能模板 的面板小程序项目。

详细操作步骤,请参考 初始化项目工程

完成以上步骤后,一个面板小程序的开发模板初始化完成。以下为工程目录的介绍:

src/
├── api/                          # API 接口层
├── components/                   # 公共组件
│   ├── icon-font/
│   ├── preview-image/
├── pages/                        # 页面
│   └── home/                     # 首页
├── redux/                        # Redux 状态管理
│   ├── modules/
├── hooks/                        # 自定义 Hooks
├── i18n/                         # 国际化
├── devices/                      # 设备相关
├── res/                          # 静态资源
├── styles/                       # 全局样式
├── utils/                        # 工具函数
├── constant/                     # 常量定义
├── app.config.ts                 # 应用配置
├── app.less                      # 全局样式
├── app.tsx                       # 应用入口
├── composeLayout.tsx             # 布局组件
├── global.config.ts              # 全局配置
├── routes.config.ts              # 路由配置
├── theme.json                    # 主题配置
└── variables.less                # 样式变量

图像导入及选择

功能介绍

模板中提供默认图像列表,用户可直接对列表中的图像进行处理。同时模板中提供了方法,支持用户通过选取相册内容或拍照获取图像。

相关代码段

import { chooseImage } from "@ray-js/ray";

// 用于保证用户选择的图像
const [list, setList] = React.useState<string[]>([]);
const handleSelectImage = useCallback(() => {
  // 选择图片
  chooseImage({
    success: res => {
      console.log('chooseCropImage success', res);
      setList(prev => [...prev, ...res.tempFilePaths]);
    },
    fail: error => {
      console.error('chooseCropImage fail', error);
    },
  });

功能介绍

通过对图像进行增强优化及畸变校正,改善 C 端用户浏览图像时的体验。

关键 API 代码段

import { ai, env } from "@ray-js/ray";

/**
 * 目前相关的能力 API 只支持单图像处理,如需处理多张图片,请采用队列方式依次调用
 */
const enhanceImages = [];
let doEnhance = false;

/**
 * 摄像头畸变参数
 * 注意:不同摄像头畸变参数不同,需根据实际摄像头参数进行调整
 */
const distortionOptions = {
  interpolationType: 2,
  ratio: 100,
  fCx: 3.108605878126431e2,
  fCy: 6.257166314880553e2,
  fFx: 7.084082701155164e2,
  fFy: 7.065142640307738e2,
  fK1: -0.291356681546637,
  fK2: 0.083781361060513,
  fK3: -0.011253071088971,
  fP1: 3.256053844769221e-4,
  fP2: 4.136029216106517e-4,
};

/**
 * 处理增强图像
 * @param data
 * @returns
 */
const handleEnhance = (data) => {
  if (doEnhance) {
    return;
  }
  doEnhance = true;
  ai.enhanceClarityForImage({
    inputImagePath: data.src,
    outputImagePath: `${env.USER_DATA_PATH}/ai_enhanced_image`,
    enhanceType: 5,
    success: (res) => {
      // 优化图像清晰度完成,这里判断是否需要做畸变校正
      if (data.type === "correct") {
        ai.enhanceCalibrationForImage({
          inputImagePath: res.outputImagePath,
          outputImagePath: `${env.USER_DATA_PATH}/ai_enhanced_image`,
          ...distortionOptions,
          success: (res1) => {
            // AI 畸变校正图片成功
            data.resolve(res1.outputImagePath);
          },
          fail: (error) => {
            // AI 畸变校正图片失败
            data.reject(error);
          },
          complete: () => {
            doEnhance = false;
            if (enhanceImages.length > 0) {
              handleEnhance(enhanceImages.shift());
            }
          },
        });
      } else {
        data.resolve(res.outputImagePath);
        doEnhance = false;
        if (enhanceImages.length > 0) {
          handleEnhance(enhanceImages.shift());
        }
      }
    },
    fail: (error) => {
      // AI 处理图片失败
      data.reject(error);
      doEnhance = false;
      if (enhanceImages.length > 0) {
        handleEnhance(enhanceImages.shift());
      }
    },
  });
};

/**
 * 增强图像
 * @param src
 * @param type
 * @returns
 */
export const enhanceImage = (src, type) => {
  return (
    new Promise() <
    string >
    ((resolve, reject) => {
      enhanceImages.push({
        src,
        type,
        resolve,
        reject,
      });
      if (!doEnhance) {
        handleEnhance(enhanceImages.shift());
      }
    })
  );
};