Skip to content
Back to skills

Hmos Scan Kit Decodeimage

ASecurity

识别NV21格式图像数据中的条形码/二维码/MULTIFUNCTIONAL CODE,支持单码/多码识别,返回码类型/码值/码位置/放大倍数,适用于相机预览流实时扫码场景

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 22, 2026
developmenttypescriptapiperformance

Works with

  • api

Security analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned September 22, 2026

npx -y skills add IsKenKenYa/skills --skill hmos-scan-kit-decodeimage --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Hmos Scan Kit Decodeimage?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Hmos Scan Kit Decodeimage
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/iskenkenya-hmos-scan-kit-decodeimage/badge)](https://www.skillsdirectory.com/skills/iskenkenya-hmos-scan-kit-decodeimage)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: hmos-scan-kit-decodeimage
description: 识别NV21格式图像数据中的条形码/二维码/MULTIFUNCTIONAL CODE,支持单码/多码识别,返回码类型/码值/码位置/放大倍数,适用于相机预览流实时扫码场景
---

# 识别图像数据技能

## 功能描述

本技能提供对NV21像素格式图像数据的扫码识别能力,支持识别条形码、二维码、MULTIFUNCTIONAL CODE等多种码类型。通过调用Scan Kit的`detectBarcode.decodeImage`接口,传入ByteImage类型的图像数据,可以获取码类型、码值、码位置、期望图像放大倍数等识别结果。该能力支持一图单码和一图多码的识别,适用于相机预览流实时扫码、条形码识别、付款码识别等场景。

**核心能力**:
- 支持NV21格式图像数据识码
- 支持单码和多码识别模式
- 返回详细的识别结果(码类型、码值、码位置、角点坐标)
- 提供相机变焦参考值
- 支持条形码、二维码、MULTIFUNCTIONAL CODE识别

## 使用场景

### 触发词
- "识别图像数据中的码"
- "解码图像中的条形码"
- "识别相机预览流中的二维码"
- "实时扫码"
- "图像数据识码"
- "NV21图像识码"
- "decodeImage"

### 能做
- 识别NV21格式的图像数据中的条形码、二维码、MULTIFUNCTIONAL CODE
- 支持一图单码和一图多码识别
- 获取码的类型、码值、码位置信息
- 获取QR码四个角点坐标
- 提供相机期望放大倍数,辅助实现自动变焦
- 处理相机预览流的实时图像数据

### 绝不做
- 不支持直接识别图片文件(使用`detectBarcode.decode`接口识别图片文件)
- 不支持非NV21格式的图像数据
- 不提供相机启动功能(需配合Camera Kit使用)
- 不在模拟器上运行(模拟器不支持)
- 不支持并行调用多个decodeImage接口

### 补充
- 图像数据来源于Camera Kit的预览流,需要使用ImageReceiver获取
- 相机预览流宽高和图像数据宽高需要正确对应(注意旋转角度)
- 需要在识别完成后再释放图像数据资源
- 返回的cornerPoints坐标需要根据屏幕方向和预览组件大小进行转换

## 调用规范和规则

### 输入约束
- **图像格式**:仅支持NV21格式
- **图像数据**:ArrayBuffer类型的byteBuffer
- **图像宽度**:正整数,单位px
- **图像高度**:正整数,单位px
- **码类型**:支持ALL、QR_CODE、CODABAR、CODE_39、CODE_93、CODE_128、CODE_11、ITF_14、PDF_417、EAN_13、EAN_8、UPC_A、UPC_E、DATA_MATRIX、AZTEC等

### 执行约束
- **API调用频次**:不支持并行调用,需等待上一次调用完成
- **图像数据有效性**:需在识别完成后再释放图像数据
- **依赖声明**:需要Camera Kit配合获取预览流数据
- **API版本要求**:HarmonyOS 5.0.0(12)及以上版本

### 内容约束
- 禁止使用模拟器运行(会返回"Emulator is not supported"错误)
- 禁止在图像数据被释放后继续访问识别结果
- 禁止并行调用decodeImage接口

### 降级约束
- **模拟器环境**:提示用户"暂不支持模拟器开发",建议使用真机
- **图像数据获取失败**:提示用户检查Camera Kit配置和ImageReceiver设置
- **识别失败**:返回错误码和错误信息,根据错误类型提供解决建议
- **码未识别**:提示用户调整相机角度、距离或光照条件

## 调用流程和步骤

### 步骤1:导入必要模块

**前置条件**:项目已配置HarmonyOS SDK

```typescript
import { detectBarcode, scanBarcode, scanCore } from '@kit.ScanKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { camera } from '@kit.CameraKit';
import { image } from '@kit.ImageKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
```

### 步骤2:配置Camera Kit并获取预览流

**前置条件**:已申请相机权限

**详细步骤**:参考Camera Kit的[双路预览](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/camera-dual-channel-preview)文档,实现双路预览功能,通过ImageReceiver获取预览流数据。

### 步骤3:准备图像数据参数

**参数说明**:
- `byteBuffer`: 图像数据(ArrayBuffer)
- `width`: 图像宽度(注意:相机预览流数据旋转90°,宽度应为相机高度的值)
- `height`: 图像高度(注意:相机预览流数据旋转90°,高度应为相机宽度的值)
- `format`: 图像格式,固定为NV21

**示例代码**:
```typescript
// 从ImageReceiver获取imgComponent: image.Component,预览流设置的宽高: width, height
function prepareByteImage(imgComponent: image.Component, width: number, height: number): detectBarcode.ByteImage {
  let byteImg: detectBarcode.ByteImage = {
    byteBuffer: imgComponent.byteBuffer,
    // 相机预览流数据旋转90°
    width: height,
    height: width,
    format: detectBarcode.ImageFormat.NV21
  };
  return byteImg;
}
```

### 步骤4:调用decodeImage接口识别图像数据

**示例代码**:
```typescript
function decodeImageBuffer(imgComponent: image.Component, width: number, height: number) {
  // 准备图像数据
  let byteImg: detectBarcode.ByteImage = {
    byteBuffer: imgComponent.byteBuffer,
    // 相机预览流数据旋转90°
    width: height,
    height: width,
    format: detectBarcode.ImageFormat.NV21
  };
  
  // 配置识码参数
  let options: scanBarcode.ScanOptions = {
    scanTypes: [scanCore.ScanType.ALL],  // 识别所有码类型
    enableMultiMode: true,                // 启用多码识别
    enableAlbum: false                    // 关闭相册功能
  };
  
  try {
    detectBarcode.decodeImage(byteImg, options).then((data: detectBarcode.DetectResult) => {
      hilog.info(0x0001, '[Scan Sample]',
        `Succeeded in getting DetectResult by promise with options, result is ${JSON.stringify(data)}`);
      
      // 处理识别结果
      if (data.scanResults && data.scanResults.length > 0) {
        data.scanResults.forEach((result, index) => {
          hilog.info(0x0001, '[Scan Sample]', 
            `Result ${index}: type=${result.scanType}, value=${result.originalValue}`);
        });
      }
      
      // 处理zoomValue(用于自动变焦)
      if (data.zoomValue) {
        hilog.info(0x0001, '[Scan Sample]', `Zoom value: ${data.zoomValue}`);
        // 可以根据zoomValue调整相机焦距
      }
    }).catch((err: BusinessError) => {
      hilog.error(0x0001, '[Scan Sample]',
        `Failed to get DetectResult by promise with options. Code: ${err.code}, message: ${err.message}`);
    });
  } catch (err) {
    hilog.error(0x0001, '[Scan Sample]', 
      `Failed to detectBarcode. Code: ${err.code}, message: ${err.message}`);
  }
}
```

### 步骤5:处理识别结果

**结果处理**:
```typescript
function processDetectResult(result: detectBarcode.DetectResult) {
  // 遍历所有识别结果
  result.scanResults.forEach((scanResult, index) => {
    // 码类型
    const scanType = scanResult.scanType;
    
    // 码值
    const originalValue = scanResult.originalValue;
    
    // 码位置(最小外接矩形)
    if (scanResult.scanCodeRect) {
      const rect = scanResult.scanCodeRect;
      hilog.info(0x0001, '[Scan Sample]', 
        `Rect: left=${rect.left}, top=${rect.top}, right=${rect.right}, bottom=${rect.bottom}`);
    }
    
    // QR码四个角点坐标
    if (scanResult.cornerPoints && scanResult.cornerPoints.length === 4) {
      const cornerPoints = scanResult.cornerPoints;
      // 需要根据屏幕方向和预览组件大小进行坐标转换
      hilog.info(0x0001, '[Scan Sample]', 
        `Corner points: ${JSON.stringify(cornerPoints)}`);
    }
  });
  
  // 相机期望放大倍数
  const zoomValue = result.zoomValue;
  // 可以用于调整相机焦距,实现自动变焦
}
```

### 步骤6:处理cornerPoints坐标转换

**坐标转换逻辑**(假设相机预览流宽高为1080*1920):

```typescript
function convertCornerPoints(cornerPoints: Array<scanBarcode.Point>, previewWidth: number, previewHeight: number) {
  // 屏幕自然方向和摄像头传感器方向不同,需要转换
  // 假设创建的相机预览流宽高为1080 * 1920
  const convertedPoints: Array<{x: number, y: number}> = [];
  
  // 右下角(x, y):(1080 - cornerPoints[0].y, cornerPoints[0].x)
  // 左下角(x, y):(1080 - cornerPoints[1].y, cornerPoints[1].x)
  // 左上角(x, y):(1080 - cornerPoints[2].y, cornerPoints[2].x)
  // 右上角(x, y):(1080 - cornerPoints[3].y, cornerPoints[3].x)
  
  if (cornerPoints && cornerPoints.length === 4) {
    convertedPoints.push({
      x: previewWidth - cornerPoints[0].y,
      y: cornerPoints[0].x
    }); // 右下角
    convertedPoints.push({
      x: previewWidth - cornerPoints[1].y,
      y: cornerPoints[1].x
    }); // 左下角
    convertedPoints.push({
      x: previewWidth - cornerPoints[2].y,
      y: cornerPoints[2].x
    }); // 左上角
    convertedPoints.push({
      x: previewWidth - cornerPoints[3].y,
      y: cornerPoints[3].x
    }); // 右上角
  }
  
  return convertedPoints;
}

// 如果预览组件XComponent的宽高和相机预览流宽高不一致,还需要缩放
function scaleCornerPoints(
  points: Array<{x: number, y: number}>,
  previewWidth: number,
  previewHeight: number,
  xComponentWidth: number,
  xComponentHeight: number
) {
  const ratio = xComponentWidth / previewWidth;
  return points.map(point => ({
    x: point.x * ratio,
    y: point.y * ratio
  }));
}
```

## 错误码说明

| 错误码 | 说明 | 解决方法 |
|-------|------|---------|
| 401 | 参数错误。可能原因:1. 参数类型不正确;2. 参数验证失败。 | 检查参数类型和取值范围,确保ByteImage对象的属性正确设置 |
| 1000500001 | 内部错误。 | 检查系统日志,确认图像数据格式正确,尝试重新调用接口 |
| 模拟器错误 | "Emulator is not supported" | 使用真机进行开发和测试 |

## 编译和修复问题

### 依赖声明
```json
{
  "dependencies": {
    "@kit.ScanKit": ">=5.0.0",
    "@kit.CameraKit": ">=5.0.0",
    "@kit.ImageKit": ">=5.0.0",
    "@kit.BasicServicesKit": ">=5.0.0",
    "@kit.PerformanceAnalysisKit": ">=5.0.0"
  }
}
```

### 环境要求
- **HarmonyOS版本**:5.0.0(12)及以上
- **开发环境**:DevEco Studio
- **运行环境**:真机(模拟器不支持)

### 常见编译问题

**问题1:导入模块失败**
```
Error: Cannot find module '@kit.ScanKit' or its corresponding type declarations.
```
**解决方法**:检查项目配置,确保已正确配置HarmonyOS SDK,并且SDK版本不低于API 12。

**问题2:类型定义错误**
```
Error: Property 'decodeImage' does not exist on type 'typeof detectBarcode'.
```
**解决方法**:确认使用的HarmonyOS版本不低于5.0.0(12),该接口从API 12开始支持。

**问题3:相机权限问题**
```
Error: Permission denied: camera
```
**解决方法**:在module.json5中添加相机权限配置:
```json
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.CAMERA"
      }
    ]
  }
}
```

## 常见问题与解决方法

### Q1:如何获取NV21格式的图像数据?
**原因**:decodeImage接口只支持NV21格式的图像数据。
**解决方法**:
- 使用Camera Kit启动相机预览流
- 配置预览流格式为NV21
- 通过ImageReceiver获取预览流的图像数据
- 参考Camera Kit的[双路预览](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/camera-dual-channel-preview)文档

### Q2:图像宽高应该传什么值?
**原因**:相机预览流数据和图像数据存在方向差异。
**解决方法**:
- 相机预览流数据通常旋转90°
- ByteImage的width应为相机预览流的height
- ByteImage的height应为相机预览流的width
- 例如:预览流设置1080*1920,ByteImage的width应为1920,height应为1080

### Q3:如何在预览组件上绘制码位置框?
**原因**:cornerPoints返回的坐标需要进行转换。
**解决方法**:
- 根据屏幕方向转换cornerPoints坐标(参考步骤6)
- 根据预览组件大小缩放坐标
- 在XComponent或Canvas组件上绘制矩形框

### Q4:识别速度慢或识别失败怎么办?
**原因**:图像质量、光照条件、码图大小等因素影响识别。
**解决方法**:
- 确保图像清晰度和分辨率足够
- 改善光照条件
- 调整相机与码图的距离
- 使用zoomValue实现自动变焦,拉近码图

### Q5:如何实现多码识别?
**原因**:需要配置多码识别模式。
**解决方法**:
- 在ScanOptions中设置`enableMultiMode: true`
- 遍历scanResults数组处理所有识别到的码
- 注意:多码识别可能影响识别速度

## 输出结果报告

执行完成后输出以下信息:

```typescript
{
  "status": "success",
  "scanResultCount": 2,  // 识别到的码数量
  "scanResults": [
    {
      "scanType": "QR_CODE",      // 码类型
      "originalValue": "https://example.com",  // 码值
      "scanCodeRect": {           // 码位置
        "left": 100,
        "top": 200,
        "right": 300,
        "bottom": 400
      },
      "cornerPoints": [           // QR码四个角点(仅QR码返回)
        {"x": 100, "y": 200},
        {"x": 100, "y": 400},
        {"x": 300, "y": 400},
        {"x": 300, "y": 200}
      ]
    }
  ],
  "zoomValue": 1.5,  // 相机期望放大倍数
  "apiUsed": [
    "detectBarcode.decodeImage",
    "detectBarcode.ByteImage",
    "scanBarcode.ScanOptions",
    "detectBarcode.DetectResult"
  ]
}
```

## 参考文档

- [API开发指南:识别图像数据](references/scan-decodeimage.md)
- [API参考:detectBarcode (图像识码)](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/scan-imagedecode)
- [API参考:scanBarcode (默认界面扫码)](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/scan-scanbarcode-api)
- [Camera Kit:双路预览](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/camera-dual-channel-preview)

## 完整示例代码

- [ArkTS示例:图像数据识码](assets/decodeimage_example.ets)

## 测试用例

### 正向测试用例
- [单码识别测试](tests/test_single_decode.ts):测试识别单个QR码
- [多码识别测试](tests/test_multi_decode.ts):测试识别多个不同类型的码
- [条形码识别测试](tests/test_barcode_decode.ts):测试识别条形码

### 边界测试用例
- [最小图像尺寸测试](tests/test_min_image_size.ts):测试最小图像尺寸识别
- [最大图像尺寸测试](tests/test_max_image_size.ts):测试最大图像尺寸识别
- [模糊图像测试](tests/test_blur_image.ts):测试模糊图像识别能力

### 异常测试用例
- [空图像数据测试](tests/test_empty_buffer.ts):测试空图像数据输入
- [错误格式测试](tests/test_wrong_format.ts):测试非NV21格式输入
- [模拟器测试](tests/test_emulator.ts):验证模拟器环境返回错误

Files in this skill

  • SUB_SKILL.md14.7 KB
  • assets/corner-points-conversion.ets964 B
  • assets/decodeImage-example.ets2.4 KB
  • assets/decodeimage_example.ets7.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…