convert-the-model-to-rknn/016新的导出rknn模型脚本.py

304 lines
11 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
PaddleOCR ONNX to RKNN Model Converter
将PaddleOCR的文本检测和文本识别ONNX模型转换为RKNN模型
"""
import os
import numpy as np
from rknn.api import RKNN
import argparse
class PaddleOCRConverter:
def __init__(self):
self.rknn = RKNN(verbose=True)
def get_quantized_dtype(self, platform, quantize):
"""
根据平台和是否量化选择合适的quantized_dtype
"""
if platform.lower() in ['rk3588']:
# RK3588支持的量化类型
return 'w8a8' if quantize else None
else:
# 其他平台 (rk3566, rk3568等)
return 'w8a8' if quantize else 'w8a16'
def convert_detection_model(self, onnx_path, rknn_path, platform='rk3588', quantize=False, dataset_path=None):
"""
转换文本检测模型
Args:
onnx_path: 输入的ONNX模型路径
rknn_path: 输出的RKNN模型路径
platform: 目标平台 (rk3588, rk3566, rk3568等)
quantize: 是否进行量化
dataset_path: 量化数据集路径
"""
print(f"开始转换文本检测模型: {onnx_path}")
# 获取适合的quantized_dtype
quantized_dtype = self.get_quantized_dtype(platform, quantize)
# 配置RKNN
config_params = {
# 'mean_values': [[123.675, 116.28, 103.53]], # PaddleOCR标准化参数
# 'std_values': [[58.395, 57.12, 57.375]],
'target_platform': platform
}
# 只有在需要时才添加quantized_dtype参数
if quantized_dtype is not None:
config_params['quantized_dtype'] = quantized_dtype
self.rknn.config(**config_params)
# 加载ONNX模型
print("加载ONNX模型...")
ret = self.rknn.load_onnx(model=onnx_path)
if ret != 0:
print(f"加载ONNX模型失败: {ret}")
return False
# 构建模型
print("构建RKNN模型...")
ret = self.rknn.build(do_quantization=quantize, dataset=dataset_path)
if ret != 0:
print(f"构建RKNN模型失败: {ret}")
return False
# 导出模型
print(f"导出RKNN模型到: {rknn_path}")
ret = self.rknn.export_rknn(rknn_path)
if ret != 0:
print(f"导出RKNN模型失败: {ret}")
return False
print("文本检测模型转换完成!")
return True
def convert_recognition_model(self, onnx_path, rknn_path, platform='rk3588', quantize=False, dataset_path=None):
"""
转换文本识别模型
Args:
onnx_path: 输入的ONNX模型路径
rknn_path: 输出的RKNN模型路径
platform: 目标平台
quantize: 是否进行量化
dataset_path: 量化数据集路径
"""
print(f"开始转换文本识别模型: {onnx_path}")
# 重新初始化RKNN实例
self.rknn.release()
self.rknn = RKNN(verbose=True)
# 获取适合的quantized_dtype
quantized_dtype = self.get_quantized_dtype(platform, quantize)
# 配置RKNN (文本识别模型的预处理参数)
config_params = {
# 'mean_values': [[127.5, 127.5, 127.5]], # 文本识别模型标准化参数
# 'std_values': [[127.5, 127.5, 127.5]],
'target_platform': platform
}
# 只有在需要时才添加quantized_dtype参数
if quantized_dtype is not None:
config_params['quantized_dtype'] = quantized_dtype
self.rknn.config(**config_params)
# 加载ONNX模型
print("加载ONNX模型...")
ret = self.rknn.load_onnx(model=onnx_path)
if ret != 0:
print(f"加载ONNX模型失败: {ret}")
return False
# 构建模型
print("构建RKNN模型...")
ret = self.rknn.build(do_quantization=quantize, dataset=dataset_path)
if ret != 0:
print(f"构建RKNN模型失败: {ret}")
return False
# 导出模型
print(f"导出RKNN模型到: {rknn_path}")
ret = self.rknn.export_rknn(rknn_path)
if ret != 0:
print(f"导出RKNN模型失败: {ret}")
return False
print("文本识别模型转换完成!")
return True
def generate_quantization_dataset(self, input_shape, num_samples=100, output_path="./dataset.txt"):
"""
生成量化数据集
Args:
input_shape: 输入形状 (N, C, H, W)
num_samples: 样本数量
output_path: 输出路径
"""
print(f"生成量化数据集: {output_path}")
# 创建数据集目录
dataset_dir = os.path.dirname(output_path)
if dataset_dir and not os.path.exists(dataset_dir):
os.makedirs(dataset_dir)
# 生成随机数据并保存
dataset_files = []
for i in range(num_samples):
# 生成随机数据 (0-255)
data = np.random.randint(0, 256, input_shape, dtype=np.uint8)
# 保存为npy文件
npy_path = f"{dataset_dir}/sample_{i}.npy"
np.save(npy_path, data)
dataset_files.append(npy_path)
# 创建数据集列表文件
with open(output_path, 'w') as f:
for file_path in dataset_files:
f.write(f"{file_path}\n")
print(f"生成了 {num_samples} 个样本的量化数据集")
return output_path
def test_model(self, rknn_path, input_shape):
"""
测试转换后的RKNN模型
Args:
rknn_path: RKNN模型路径
input_shape: 输入形状
"""
print(f"测试RKNN模型: {rknn_path}")
# 重新初始化RKNN实例用于推理
test_rknn = RKNN(verbose=False)
# 加载RKNN模型
ret = test_rknn.load_rknn(rknn_path)
if ret != 0:
print(f"加载RKNN模型失败: {ret}")
return False
# 初始化运行环境
ret = test_rknn.init_runtime()
if ret != 0:
print(f"初始化运行环境失败: {ret}")
return False
# 生成测试数据
test_data = np.random.randint(0, 256, input_shape, dtype=np.uint8)
# 进行推理
outputs = test_rknn.inference(inputs=[test_data])
print(f"推理成功! 输出形状: {[output.shape for output in outputs]}")
# 释放资源
test_rknn.release()
return True
def release(self):
"""释放RKNN资源"""
self.rknn.release()
def main():
parser = argparse.ArgumentParser(description='将PaddleOCR ONNX模型转换为RKNN模型')
parser.add_argument('--det_onnx', type=str, required=True, help='文本检测ONNX模型路径')
parser.add_argument('--rec_onnx', type=str, required=True, help='文本识别ONNX模型路径')
parser.add_argument('--output_dir', type=str, default='./rknn_models', help='RKNN模型输出目录')
parser.add_argument('--platform', type=str, default='rk3588', help='目标平台')
parser.add_argument('--quantize', action='store_true', help='是否进行量化')
parser.add_argument('--test', action='store_true', help='是否测试转换后的模型')
args = parser.parse_args()
# 创建输出目录
os.makedirs(args.output_dir, exist_ok=True)
# 初始化转换器
converter = PaddleOCRConverter()
try:
# 定义输入形状
det_input_shape = (1, 3, 640, 640) # 文本检测模型输入形状
rec_input_shape = (1, 3, 48, 320) # 文本识别模型输入形状
# 生成量化数据集(如果需要量化)
det_dataset_path = None
rec_dataset_path = None
if args.quantize:
print("生成量化数据集...")
det_dataset_path = converter.generate_quantization_dataset(
det_input_shape, num_samples=100,
output_path=os.path.join(args.output_dir, "det_dataset.txt")
)
rec_dataset_path = converter.generate_quantization_dataset(
rec_input_shape, num_samples=100,
output_path=os.path.join(args.output_dir, "rec_dataset.txt")
)
# 转换文本检测模型
det_rknn_path = os.path.join(args.output_dir, "text_detection.rknn")
success = converter.convert_detection_model(
args.det_onnx, det_rknn_path, args.platform, args.quantize, det_dataset_path
)
if not success:
print("文本检测模型转换失败!")
return
# 转换文本识别模型
rec_rknn_path = os.path.join(args.output_dir, "text_recognition.rknn")
success = converter.convert_recognition_model(
args.rec_onnx, rec_rknn_path, args.platform, args.quantize, rec_dataset_path
)
if not success:
print("文本识别模型转换失败!")
return
# 测试模型(如果指定)
if args.test:
print("\n开始测试转换后的模型...")
converter.test_model(det_rknn_path, det_input_shape)
converter.test_model(rec_rknn_path, rec_input_shape)
print(f"\n所有模型转换完成!")
print(f"文本检测模型: {det_rknn_path}")
print(f"文本识别模型: {rec_rknn_path}")
finally:
converter.release()
if __name__ == "__main__":
# 如果直接运行脚本,提供示例用法
'''
python 016新的导出rknn模型脚本.py --det_onnx /home/admin-root/haotian/康达瑞贝斯机器狗/det_mobile_14_shape.onnx --rec_onnx /home/admin-root/haotian/康达瑞贝斯机 器狗/rec_mobile_14_shape.onnx --platform rk3588 --output_dir ./models
'''
if len(os.sys.argv) == 1:
print("PaddleOCR ONNX to RKNN Model Converter")
print("\n使用示例:")
print("python paddleocr_converter.py \\")
print(" --det_onnx ./text_detection.onnx \\")
print(" --rec_onnx ./text_recognition.onnx \\")
print(" --output_dir ./rknn_models \\")
print(" --platform rk3588 \\")
print(" --quantize \\")
print(" --test")
print("\n参数说明:")
print(" --det_onnx: 文本检测ONNX模型路径")
print(" --rec_onnx: 文本识别ONNX模型路径")
print(" --output_dir: RKNN模型输出目录")
print(" --platform: 目标平台 (rk3588, rk3566, rk3568等)")
print(" --quantize: 是否进行量化")
print(" --test: 是否测试转换后的模型")
else:
main()