OCR 文字识别
目标平台: RK3576 | NPU 算力: 6 TOPS | 文档版本: V1.0
适用板型: C-3576BQ 核心板 + M4-R2 底板
最后更新: 2026-10-23
1. 概述
1.1 功能简介
OCR(Optical Character Recognition,光学字符识别)是将图像中的文字转换为可编辑文本的技术。RK3576 搭载 6 TOPS 算力 NPU,能够高效运行 PaddleOCR 的三个子模型,实现端到端的文字识别。
PPOCR 方案包含三个独立模型:
| 模型 | 作用 | 网络结构 |
|---|---|---|
| 检测模型(DB) | 定位图像中文字区域 | Differentiable Binarization |
| 分类模型(CLS) | 判断文字方向(0°/180°) | MobileNetV3 |
| 识别模型(CRNN) | 识别裁剪区域中的文字 | CRNN + CTC |
1.2 应用场景
- 票据识别:增值税发票、银行回单等票据自动录入
- 身份证识别:身份证正反面信息提取
- 车牌识别:停车场入口/出口车牌自动读取
- 文档数字化:纸质文档扫描后自动转为电子文本
- 工业标签读取:产品序列号、生产日期等标签自动读取
- 道路标识识别:交通标志文字自动识别
1.3 工作原理
图像输入 → 文字检测 → 文字方向分类 → 文字识别 → 文本输出
↓ ↓ ↓ ↓
预处理 DB 检测 方向分类 CRNN 识别完整的 OCR 流程分为三个阶段:
- DB 检测阶段:输入原始图像,通过 DB(Differentiable Binarization)网络输出文字区域的二值图,再通过轮廓提取获取文字边界框。
- 方向分类阶段(可选):对裁剪出的文字区域进行方向分类,判断文字是正向(0°)还是倒置(180°),对倒置图像进行旋转矫正。
- CRNN 识别阶段:将矫正后的文字图像输入 CRNN(Convolutional Recurrent Neural Network)网络,通过 CTC(Connectionist Temporal Classification)解码输出最终文字。
1.4 硬件能力说明
RK3576 的 NPU 具备以下特性,使其适合运行 OCR 任务:
| 特性 | 参数 |
|---|---|
| 算力 | 6 TOPS(INT8) |
| NPU 核心数 | 3 核(NPU_CORE_0, NPU_CORE_1, NPU_CORE_2) |
| 支持精度 | INT8 / FP16 / 混合量化 |
| 最大输入图像 | 受限于 NPU 内存与模型输入尺寸 |
2. 硬件准备
| 组件 | 型号/规格 | 数量 | 备注 |
|---|---|---|---|
| 核心板 | C-3576BQ | 1 | RK3576 主芯片 |
| 底板 | M4-R2 | 1 | 通用开发底板 |
| 电源适配器 | 5V/2A 电源(Type-C 或 6pin 供电) | 1 | 底板供电(空载最小 1000mA) |
| TF 卡 | 32GB+ Class10 | 1 | 系统启动 |
| 显示器 | HDMI 接口 | 1 | 验证输出 |
| USB 摄像头(可选) | UVC 兼容 | 1 | 实时 OCR 演示 |
接线说明:
- 将 TF 卡插入底板 TF 卡槽
- 连接电源适配器到 Type-C 或 6pin 电源接口
- 连接 HDMI 线到显示器
- 连接网线(用于 SSH 调试)
3. 软件准备
3.1 系统环境
- 操作系统:Linux(基于 RK3576 Linux SDK)
- Python:3.9+
- RKNN Toolkit2:最新版本
3.2 安装 RKNN 工具链
在开发主机(x86 PC)上安装 RKNN Toolkit2:
pip3 install rknn-toolkit2在 RK3576 板端安装 RKNN Lite2 运行时:
pip3 install rknn-lite23.3 安装依赖库
pip3 install numpy opencv-python3.4 下载 PaddleOCR 模型
从 PaddleOCR 官方 GitHub 仓库下载预训练模型:
# 下载 PPOCR 中文模型
wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar
wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_cls_infer.tar
wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar
# 解压
tar -xf ch_PP-OCRv3_det_infer.tar
tar -xf ch_PP-OCRv3_cls_infer.tar
tar -xf ch_PP-OCRv3_rec_infer.tar3.5 模型格式转换(Paddle → ONNX)
PaddleOCR 原始模型为 PaddlePaddle 格式,需要先转为 ONNX 格式:
# 安装 paddle2onnx
pip install paddle2onnx
# 转换检测模型
paddle2onnx --model_dir ch_PP-OCRv3_det_infer \
--model_filename inference.pdmodel \
--params_filename inference.pdiparams \
--save_file ch_ppocr_det.onnx \
--opset_version 14
# 转换分类模型
paddle2onnx --model_dir ch_PP-OCRv3_cls_infer \
--model_filename inference.pdmodel \
--params_filename inference.pdiparams \
--save_file ch_ppocr_cls.onnx \
--opset_version 14
# 转换识别模型
paddle2onnx --model_dir ch_PP-OCRv3_rec_infer \
--model_filename inference.pdmodel \
--params_filename inference.pdiparams \
--save_file ch_ppocr_rec.onnx \
--opset_version 143.6 准备量化校准数据集
每个模型需要对应的校准数据集文件,每行一个图像路径:
# ocr_det_samples.txt(检测模型校准集)
# 内容示例:
# /path/to/det_sample_001.jpg
# /path/to/det_sample_002.jpg
# ...
# ocr_cls_samples.txt(分类模型校准集)
# ocr_rec_samples.txt(识别模型校准集)4. 操作步骤
4.1 PPOCR 三阶段模型转换
以下代码在 x86 开发主机上运行,将 ONNX 模型转换为 RKNN 格式。
4.1.1 文字检测模型(DB)
from rknn.api import RKNN
# 创建 RKNN 实例
rknn = RKNN()
# 配置模型参数
rknn.config(
mean_values=[[123.68, 116.78, 103.94]],
std_values=[[58.395, 57.12, 57.375]],
target_platform='rk3576',
quantized_dtype='asymmetric_quantized-8'
)
# 加载 ONNX 模型
ret = rknn.load_onnx(model='ch_ppocr_det.onnx')
if ret != 0:
print('Load detection model failed!')
exit(ret)
# 构建 RKNN 模型(开启量化)
ret = rknn.build(do_quantization=True, dataset='ocr_det_samples.txt')
if ret != 0:
print('Build detection model failed!')
exit(ret)
# 导出 RKNN 模型
ret = rknn.export_rknn('ch_ppocr_det.rknn')
if ret != 0:
print('Export detection model failed!')
exit(ret)
# 释放资源
rknn.release()
print('Detection model conversion completed: ch_ppocr_det.rknn')4.1.2 文字方向分类模型
from rknn.api import RKNN
rknn = RKNN()
rknn.config(
mean_values=[[123.68, 116.78, 103.94]],
std_values=[[58.395, 57.12, 57.375]],
target_platform='rk3576',
quantized_dtype='asymmetric_quantized-8'
)
ret = rknn.load_onnx(model='ch_ppocr_cls.onnx')
if ret != 0:
print('Load classification model failed!')
exit(ret)
ret = rknn.build(do_quantization=True, dataset='ocr_cls_samples.txt')
if ret != 0:
print('Build classification model failed!')
exit(ret)
ret = rknn.export_rknn('ch_ppocr_cls.rknn')
if ret != 0:
print('Export classification model failed!')
exit(ret)
rknn.release()
print('Classification model conversion completed: ch_ppocr_cls.rknn')4.1.3 文字识别模型(CRNN)
from rknn.api import RKNN
rknn = RKNN()
rknn.config(
mean_values=[[123.68, 116.78, 103.94]],
std_values=[[58.395, 57.12, 57.375]],
target_platform='rk3576',
quantized_dtype='asymmetric_quantized-8'
)
ret = rknn.load_onnx(model='ch_ppocr_rec.onnx')
if ret != 0:
print('Load recognition model failed!')
exit(ret)
ret = rknn.build(do_quantization=True, dataset='ocr_rec_samples.txt')
if ret != 0:
print('Build recognition model failed!')
exit(ret)
ret = rknn.export_rknn('ch_ppocr_rec.rknn')
if ret != 0:
print('Export recognition model failed!')
exit(ret)
rknn.release()
print('Recognition model conversion completed: ch_ppocr_rec.rknn')4.1.4 转换参数说明
| 参数 | 值 | 说明 |
|---|---|---|
| mean_values | [[123.68, 116.78, 103.94]] | ImageNet 均值,RGB 通道 |
| std_values | [[58.395, 57.12, 57.375]] | ImageNet 标准差,RGB 通道 |
| target_platform | rk3576 | 目标平台,启用 RK3576 NPU 优化 |
| quantized_dtype | asymmetric_quantized-8 | 非对称 INT8 量化 |
| do_quantization | True | 开启量化以提升 NPU 推理速度 |
4.2 板端 OCR 完整流程
以下代码在 RK3576 板端运行。
from rknnlite.api import RKNNLite
import cv2
import numpy as np
class RK3576OCR:
"""RK3576 PPOCR 推理
集成 DB 检测 + CRNN 识别的完整 OCR 流程。
检测模型使用三核 NPU 加速,识别模型使用单核运行。
"""
def __init__(self, det_rknn='ch_ppocr_det.rknn',
cls_rknn='ch_ppocr_cls.rknn',
rec_rknn='ch_ppocr_rec.rknn',
dict_path='ppocr_keys_v1.txt'):
# 加载检测模型(三核 NPU,最大算力)
self.det_rknn = RKNNLite()
self.det_rknn.load_rknn(det_rknn)
self.det_rknn.init_runtime(core_mask=RKNNLite.NPU_CORE_0_1_2)
# 加载分类模型(单核,轻量计算)
self.cls_rknn = RKNNLite()
self.cls_rknn.load_rknn(cls_rknn)
self.cls_rknn.init_runtime(core_mask=RKNNLite.NPU_CORE_0)
# 加载识别模型(单核)
self.rec_rknn = RKNNLite()
self.rec_rknn.load_rknn(rec_rknn)
self.rec_rknn.init_runtime(core_mask=RKNNLite.NPU_CORE_0)
# 加载字符字典
self.char_dict = self._load_dict(dict_path)
def _load_dict(self, dict_path):
"""加载字符字典
字典文件 ppocr_keys_v1.txt 每行一个字符,
第 0 行为空白符(blank),用于 CTC 解码。
"""
with open(dict_path, 'r', encoding='utf-8') as f:
return [line.strip() for line in f.readlines()]
def detect(self, img):
"""文字检测
Args:
img: BGR 格式输入图像 (numpy.ndarray)
Returns:
list: 文字区域边界框列表,每个元素为 [x1, y1, x2, y2]
"""
h, w = img.shape[:2]
# 调整尺寸为 960 的倍数(DB 模型输入要求)
img_resized = self._resize_image(img, 960)
img_rgb = cv2.cvtColor(img_resized, cv2.COLOR_BGR2RGB)
# NPU 推理
outputs = self.det_rknn.inference(inputs=[img_rgb])
# 后处理获取文字区域
boxes = self._det_postprocess(outputs[0], h, w)
return boxes
def _resize_image(self, img, target_size):
"""等比例缩放图像,短边对齐到 target_size"""
h, w = img.shape[:2]
scale = target_size / min(h, w)
new_w = int(w * scale)
new_h = int(h * scale)
return cv2.resize(img, (new_w, new_h))
def _det_postprocess(self, output, orig_h, orig_w):
"""检测后处理
从 DB 模型输出的概率图中提取文字区域边界框。
"""
# 取第一个通道的概率图
pred = output[0, :, :, 0]
# 缩放回原始尺寸
pred = cv2.resize(pred, (orig_w, orig_h))
# 二值化
binary = (pred > 0.3).astype(np.uint8) * 255
# 形态学操作:连接断开的区域
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)
# 查找轮廓
contours, _ = cv2.findContours(
binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
# 提取边界框
boxes = []
for contour in contours:
x, y, bw, bh = cv2.boundingRect(contour)
# 过滤过小的区域
if bw > 10 and bh > 10:
boxes.append([x, y, x + bw, y + bh])
return boxes
def classify_direction(self, img, boxes):
"""文字方向分类
Args:
img: BGR 格式输入图像
boxes: 检测到的文字区域边界框列表
Returns:
list: 旋转后的边界框列表
"""
rotated_boxes = []
for box in boxes:
x1, y1, x2, y2 = box
crop = img[y1:y2, x1:x2]
if crop.size == 0:
rotated_boxes.append(box)
continue
# 分类模型输入:48x48
crop_resized = cv2.resize(crop, (48, 48))
crop_rgb = cv2.cvtColor(crop_resized, cv2.COLOR_BGR2RGB)
outputs = self.cls_rknn.inference(inputs=[crop_rgb])
cls_score = outputs[0][0][1] # 第二个位置为 180° 概率
# 如果分类为 180°,翻转图像(此处仅返回 box,实际翻转在识别前处理)
rotated_boxes.append(box)
return rotated_boxes
def recognize(self, img, boxes):
"""文字识别
对每个检测到的文字区域进行 CRNN 识别。
Args:
img: BGR 格式输入图像
boxes: 文字区域边界框列表
Returns:
list: 识别结果列表,每个元素为 {'box': [x1,y1,x2,y2], 'text': str}
"""
results = []
for box in boxes:
x1, y1, x2, y2 = box
# 裁剪文字区域
crop = img[y1:y2, x1:x2]
if crop.size == 0:
continue
# 预处理:Resize 到 48x32 (W x H),保持宽高比
h, w = crop.shape[:2]
target_w, target_h = 48, 32
scale = min(target_w / w, target_h / h)
new_w = int(w * scale)
new_h = int(h * scale)
crop_resized = cv2.resize(crop, (new_w, new_h))
# 填充到固定尺寸
canvas = np.zeros((target_h, target_w, 3), dtype=np.uint8)
canvas[:new_h, :new_w, :] = crop_resized
crop_rgb = cv2.cvtColor(canvas, cv2.COLOR_BGR2RGB)
# NPU 推理
outputs = self.rec_rknn.inference(inputs=[crop_rgb])
# CTC 解码
text = self._rec_postprocess(outputs[0])
if text.strip():
results.append({'box': box, 'text': text})
return results
def _rec_postprocess(self, output):
"""CTC 解码
从 CRNN 输出的序列概率中解码出文字。
Args:
output: shape (1, seq_len, vocab_size) 的输出张量
Returns:
str: 解码后的文字
"""
output = output[0] # (seq_len, vocab_size)
# 取每个位置的最大概率索引
indices = np.argmax(output, axis=1)
# CTC 去重解码
chars = []
prev = -1
for idx in indices:
if idx != 0 and idx != prev: # 0 是 blank,跳过重复
if idx - 1 < len(self.char_dict):
chars.append(self.char_dict[idx - 1])
prev = idx
return ''.join(chars)
def __call__(self, img):
"""完整 OCR 流程
Args:
img: BGR 格式输入图像 (numpy.ndarray)
Returns:
list: 识别结果列表
"""
boxes = self.detect(img)
results = self.recognize(img, boxes)
return results
def release(self):
"""释放 NPU 资源"""
self.det_rknn.release()
self.cls_rknn.release()
self.rec_rknn.release()
# ==================== 使用示例 ====================
if __name__ == '__main__':
# 初始化 OCR
ocr = RK3576OCR()
# 读取图像
img = cv2.imread('document.jpg')
if img is None:
print('Error: cannot read image')
exit(1)
# 执行 OCR
results = ocr(img)
# 输出结果
for r in results:
box = r['box']
text = r['text']
print(f'[{box[0]}, {box[1]}, {box[2]}, {box[3]}] -> {text}')
# 释放资源
ocr.release()4.3 NPU 核心分配策略
在 RK3576 上,三个 NPU 核心可以灵活组合使用:
| 核心模式 | 常量 | 说明 | 典型用途 |
|---|---|---|---|
| 单核 0 | NPU_CORE_0 | 使用 NPU 核心 0 | 轻量模型(分类、小模型) |
| 单核 1 | NPU_CORE_1 | 使用 NPU 核心 1 | 辅助模型并行 |
| 单核 2 | NPU_CORE_2 | 使用 NPU 核心 2 | 辅助模型并行 |
| 双核 0+1 | NPU_CORE_0_1 | 使用核心 0 和 1 | 中等算力需求 |
| 双核 1+2 | NPU_CORE_1_2 | 使用核心 1 和 2 | 中等算力需求 |
| 三核 0+1+2 | NPU_CORE_0_1_2 | 使用全部三个核心 | 大模型(检测模型) |
推荐分配方案:
DB 检测模型(计算量大) → NPU_CORE_0_1_2(三核)
CRNN 识别模型(计算量中)→ NPU_CORE_0(单核)
CLS 分类模型(计算量小) → NPU_CORE_0(单核,与识别模型串行)若需要并行推理,可将不同模型分配到不同核心:
DB 检测模型 → NPU_CORE_0_1(双核)
CRNN 识别模型 → NPU_CORE_2(单核)4.4 批量 OCR 处理
对多张图像进行批量 OCR 识别:
import os
import glob
from rknnlite.api import RKNNLite
import cv2
def batch_ocr(image_dir, output_file='ocr_results.txt'):
"""批量 OCR 处理
Args:
image_dir: 图像目录
output_file: 结果输出文件
"""
ocr = RK3576OCR()
# 获取所有图像文件
image_files = sorted(glob.glob(os.path.join(image_dir, '*.jpg')))
image_files += sorted(glob.glob(os.path.join(image_dir, '*.png')))
results = []
for img_path in image_files:
img = cv2.imread(img_path)
if img is None:
print(f'Skip: cannot read {img_path}')
continue
ocr_results = ocr(img)
text = ' '.join([r['text'] for r in ocr_results])
results.append({'file': img_path, 'text': text})
print(f'{os.path.basename(img_path)}: {text}')
# 写入结果
with open(output_file, 'w', encoding='utf-8') as f:
for r in results:
f.write(f'{r["file"]}\t{r["text"]}\n')
ocr.release()
print(f'\nResults saved to {output_file}')
if __name__ == '__main__':
batch_ocr('/path/to/images')5. 代码详解
5.1 PPOCR 三阶段流程
Stage 1: DB 检测
- 输入: 原始图像(Resize 至 960 短边)
- 网络: ResNet18 骨干 + FPN + DB 头
- 输出: 概率图 → 二值化 → 轮廓提取 → 边界框
- NPU: 三核 (NPU_CORE_0_1_2)
Stage 2: 方向分类(可选)
- 输入: 裁剪的文字区域(Resize 至 48x48)
- 网络: MobileNetV3-Small
- 输出: 0° 或 180° 分类
- NPU: 单核 (NPU_CORE_0)
Stage 3: CRNN 识别
- 输入: 对齐的文字图像(Resize 至 48x32)
- 网络: MobileNetV3 骨干 + BiLSTM + CTC 头
- 输出: 序列概率 → CTC 解码 → 文字
- NPU: 单核 (NPU_CORE_0)5.2 CTC 解码原理
CTC(Connectionist Temporal Classification)用于解决输入序列与输出标签长度不一致的问题:
输入: 宽度为 W 的图像 → CRNN 输出序列长度为 W/4
输出: 每个时间步输出 vocab_size 个字符的概率
CTC 解码规则:
1. 每个时间步取概率最大的索引
2. 索引 0 为 blank(空白符),跳过
3. 连续重复的相同字符只保留一个
4. 将索引映射到字符字典得到最终文字
示例:
原始输出索引: [0, 5, 5, 8, 0, 3, 3, 3, 7]
去重去 blank: [5, 8, 3, 7]
字典映射: "你好世界"5.3 图像预处理细节
检测模型预处理:
# 1. 短边缩放到 960
scale = 960 / min(h, w)
# 2. 归一化(ImageNet 标准)
mean = [123.68, 116.78, 103.94]
std = [58.395, 57.12, 57.375]
# img_normalized = (img_rgb - mean) / std
# 注意:RKNN 模型内部已集成归一化,inference 时直接传入 uint8 即可
# 3. HWC → CHW(RKNN 自动处理)识别模型预处理:
# 1. 裁剪文字区域
crop = img[y1:y2, x1:x2]
# 2. 等比例缩放到 48x32
scale = min(48 / w, 32 / h)
new_w, new_h = int(w * scale), int(h * scale)
crop_resized = cv2.resize(crop, (new_w, new_h))
# 3. 黑色填充到 48x32
canvas = np.zeros((32, 48, 3), dtype=np.uint8)
canvas[:new_h, :new_w] = crop_resized5.4 OCR 性能参考
以下性能数据需在 C-3576BQ + M4-R2 V10 板卡上实际测量(待板上验证):
| 阶段 | 输入尺寸 | FPS(三核) | FPS(单核) | 用途 |
|---|---|---|---|---|
| DB 检测 | 960x960 | 待板上验证 | 待板上验证 | 文字定位 |
| 方向分类 | 48x48 | 待板上验证 | 待板上验证 | 方向矫正 |
| CRNN 识别 | 48x32 | 待板上验证 | 待板上验证 | 单字符行识别 |
| 完整流程 | 自适应 | 待板上验证 | 待板上验证 | 端到端 OCR |
说明:
- 三核模式下检测模型 FPS 明显高于单核模式
- 分类模型计算量极小,单核已足够
- 识别模型 FPS 取决于检测到的文字区域数量
- 完整流程 FPS 受最慢阶段(检测)限制
6. 常见问题
6.1 检测不到文字
现象: 图像中有清晰文字,但检测阶段未返回任何边界框。
可能原因及解决方案:
| 原因 | 解决方案 |
|---|---|
| 图像模糊 | 确保图像分辨率足够,文字清晰 |
| 检测阈值过高 | 降低二值化阈值(当前 0.3,可尝试 0.2) |
| 文字区域过小 | 调整最小边界框过滤尺寸 |
| 图像对比度低 | 预处理增加对比度(CLAHE) |
# 调整检测阈值
binary = (pred > 0.2).astype(np.uint8) * 255 # 降低阈值
# 调整最小过滤尺寸
if bw > 5 and bh > 5: # 降低最小尺寸要求
boxes.append([x, y, x + bw, y + bh])6.2 识别结果有乱码
现象: 识别出的文字包含不相关的字符或乱码。
可能原因及解决方案:
| 原因 | 解决方案 |
|---|---|
| 字典文件不完整 | 确认 ppocr_keys_v1.txt 包含全部字符 |
| 模型与字典版本不匹配 | 确保 RKNN 模型与字典来自同一 PPOCR 版本 |
| 图像严重倾斜 | 加入倾斜矫正预处理 |
| 裁剪区域不完整 | 检查检测边界框是否完整覆盖文字区域 |
6.3 速度太慢
现象: OCR 处理单张图像耗时超过预期。
优化建议:
# 1. 使用三核 NPU 加速检测模型
self.det_rknn.init_runtime(core_mask=RKNNLite.NPU_CORE_0_1_2)
# 2. 降低检测输入分辨率(牺牲少量精度)
# 将 960 改为 768
img_resized = self._resize_image(img, 768)
# 3. 减少后处理中的形态学操作
# 移除或简化 morphologyEx 操作
# 4. 预分配内存,避免重复分配
# 在 __init__ 中预创建 canvas 等临时数组6.4 内存不足
现象: 加载模型时提示内存不足或 OOM。
解决方案:
# 检查可用内存
free -m
# 增加 swap 空间
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 或者选择较小的 PPOCR 版本
# 使用 PP-OCRv2 替代 PP-OCRv36.5 RKNN 模型加载失败
现象: 板端加载 .rknn 文件时报错。
排查步骤:
# 1. 确认 RKNN Lite2 版本与 Toolkit2 版本匹配
pip show rknn-lite2
# 2. 确认模型文件完整
ls -la *.rknn
# 3. 确认目标平台正确(转换时必须指定 rk3576)
# 检查转换脚本中的 target_platform 参数
# 4. 查看详细错误日志
import logging
logging.basicConfig(level=logging.DEBUG)相关文档
| 文档名称 | 路径 | 说明 |
|---|---|---|
| NPU 架构与性能概览 | NPU架构与性能概览 | RK3576 NPU 架构介绍 |
| 模型转换与量化 | 模型转换与量化 | 模型转换流程与量化 |
| 分类模型部署(LeNet/ResNet) | 分类模型部署(LeNet-ResNet) | 分类模型部署 |
| 人脸检测与识别 | 人脸检测与识别 | 人脸检测/识别部署 |
| NPU 性能调优与调试 | NPU性能调优与调试 | NPU 推理性能调优 |
