ppocrv6中的字符识别模型转ncnn平台 一、下载模型去官网下载字符识别模型https://github.com/PaddlePaddle/PaddleOCR/blob/main/readme/README_cn.md我进了魔塔社区里面有基本使用样例二、使用pnxx转模型记录一下所有步骤1使用ncnn转在系统环境下 git clone --recursive https://github.com/Tencent/ncnn.git cd ncnn mkdir build cd build git submodule update --init cmake -DCMAKE_BUILD_TYPERelease -DNCNN_VULKANON -DNCNN_BUILD_EXAMPLESON .. cmake --build . -j$(nproc) ./ncnn/build/tools/onnx/onnx2ncnn inference_sim.onnx rec.param rec.bin2使用pnxx转模型1. 访问 PNNX 官方发布页面前往https://github.com/pnnx/pnnx/releases2. 下载对应系统的二进制包Linux (Ubuntu): 下载 pnnx-xxx-ubuntu.zip3. 解压后找到 pnnx./pnnx /home/fuxueping/4tdisk/code/paddle_ocr/official_models/PP-OCRv6_medium_rec_onnx/inference.onnx inputshape[1,3,48,128] inputshape2[1,3,48,512]可参考paddleocr转ncnn及验证_ncnn paddleocrv5-CSDN博客转的过程中的输出结果pnnxparam /home/XXX/4tdisk/code/paddle_ocr/official_models/PP-OCRv6_medium_rec_onnx/inference.pnnx.param pnnxbin /home/XXX/4tdisk/code/paddle_ocr/official_models/PP-OCRv6_medium_rec_onnx/inference.pnnx.bin pnnxpy /home/XXX/4tdisk/code/paddle_ocr/official_models/PP-OCRv6_medium_rec_onnx/inference_pnnx.py pnnxonnx /home/XXX/4tdisk/code/paddle_ocr/official_models/PP-OCRv6_medium_rec_onnx/inference.pnnx.onnx ncnnparam /home/XXX/4tdisk/code/paddle_ocr/official_models/PP-OCRv6_medium_rec_onnx/inference.ncnn.param ncnnbin /home/XXX/4tdisk/code/paddle_ocr/official_models/PP-OCRv6_medium_rec_onnx/inference.ncnn.bin ncnnpy /home/XXX/4tdisk/code/paddle_ocr/official_models/PP-OCRv6_medium_rec_onnx/inference_ncnn.py fp16 1 optlevel 2 device cpu inputshape [1,3,48,128]f32 inputshape2 [1,3,48,512]f32 input input2 customop moduleop get inputshape from traced inputs inputshape [1,3,48,128]f32 inputshape2 [1,3,48,512]f32 ############# pass_level0 onnx inline_containers ... 0.01ms eliminate_noop ... 13.52ms fold_constants ... 1.27ms canonicalize ... 2.48ms shape_inference ... 2026-06-30 17:52:25.899343269 [W:onnxruntime:pnnx, cpuid_info.cc:95 LogEarlyWarning] Unknown CPU vendor. cpuinfo_vendor value: 0 2026-06-30 17:52:25.899720281 [W:onnxruntime:pnnx, device_discovery.cc:283 GetGpuDevices] Failed to detect devices under /sys/class/drm/card0: device_discovery.cc:93 ReadFileContents Failed to open file: /sys/class/drm/card0/device/vendor 865.24ms fold_constants_dynamic_shape ... 334.99ms inline_if_graph ... 0.13ms fuse_constant_as_attribute ... 0.42ms eliminate_noop_with_shape ... 0.35ms ┌────────────────────┬──────────┬──────────┐ │ │ orig │ opt │ ├────────────────────┼──────────┼──────────┤ │ node │ 508 │ 358 │ │ initializer │ 254 │ 218 │ │ functions │ 0 │ 0 │ ├────────────────────┼──────────┼──────────┤ │ nn module op │ 0 │ 0 │ │ custom module op │ 0 │ 0 │ │ aten op │ 0 │ 0 │ │ prims op │ 0 │ 0 │ │ onnx native op │ 508 │ 358 │ ├────────────────────┼──────────┼──────────┤ │ Add │ 109 │ 109 │ │ AveragePool │ 1 │ 1 │ │ BatchNormalization │ 3 │ 3 │ │ Concat │ 3 │ 2 │ │ Conv │ 62 │ 62 │ │ Div │ 19 │ 19 │ │ Erf │ 14 │ 14 │ │ HardSigmoid │ 6 │ 6 │ │ Identity │ 143 │ 0 │ │ MatMul │ 13 │ 13 │ │ MaxPool │ 1 │ 1 │ │ Mul │ 46 │ 46 │ │ Pow │ 5 │ 5 │ │ ReduceMean │ 16 │ 16 │ │ Relu │ 11 │ 11 │ │ Reshape │ 8 │ 6 │ │ Shape │ 4 │ 1 │ │ Sigmoid │ 5 │ 5 │ │ Slice │ 8 │ 7 │ │ Softmax │ 3 │ 3 │ │ Sqrt │ 5 │ 5 │ │ Squeeze │ 8 │ 8 │ │ Sub │ 5 │ 5 │ │ Transpose │ 9 │ 9 │ │ Unsqueeze │ 1 │ 1 │ └────────────────────┴──────────┴──────────┘ ############# pass_level1 onnx ############# pass_level2 ############# pass_level3 ############# pass_level4 ############# pass_level5 ############# pass_ncnn model inputshape [1,3,48,?]f32 FLOPS 1.47M memory OPS 745.89K模型转成功三、测试验证测试代码测试pnnx转出来的模型#!/usr/bin/env python3 PP-OCRv6 NCNN 模型测试 (PNNX转换版本) 测试图片: 059279805_2.jpg 预期内容: ROU 问题排查 1. 测试脚本宽度设置错误 (128 vs 320) 2. 需要验证预处理是否正确 import os import cv2 import numpy as np import yaml import ncnn script_dir os.path.dirname(os.path.abspath(__file__)) model_dir os.path.join(script_dir, official_models/PP-OCRv6_medium_rec_onnx/pnnx) img_path os.path.join(script_dir, 2PZfbirjfxA88695lRmgk.jpeg) #可自行替换 print( * 60) print(PP-OCRv6 NCNN 模型测试 (PNNX版本)) print( * 60) # 加载字符字典 with open(os.path.join(script_dir, official_models/PP-OCRv6_medium_rec_onnx/inference.yml), r, encodingutf-8) as f: character yaml.safe_load(f)[PostProcess][character_dict] print(f字符字典大小: {len(character)}) # 加载图像 img cv2.imread(img_path) if img is None: print(f错误: 无法加载图像 {img_path}) exit(1) print(f原始图像尺寸: {img.shape}) # 正确预处理 (参考PP-OCR动态宽度方式): # 1. 等比例缩放到高度48 # 2. 宽度向上取整到8的倍数模型要求 # 3. 不使用固定宽度padding直接使用计算出的宽度 h, w img.shape[:2] target_h 48 # 动态计算宽度向上取整到8的倍数 new_w (int(target_h / h * w) 7) // 8 * 8 resized cv2.resize(img, (new_w, target_h)) print(f预处理后尺寸: {resized.shape}) # BGR转RGB, 归一化, CHW格式 rgb cv2.cvtColor(resized, cv2.COLOR_BGR2RGB) data rgb.astype(np.float32) / 255.0 data_chw data.transpose(2, 0, 1) # (C, H, W) print(f输入尺寸 (CHW): {data_chw.shape}) # 加载模型 param_file os.path.join(model_dir, inference.ncnn.param) bin_file os.path.join(model_dir, inference.ncnn.bin) net ncnn.Net() net.load_param(param_file) net.load_model(bin_file) print(f模型加载成功) # 创建NCNN Mat # NCNN Mat: widthnew_w, height48, channels3 # 数据格式: 每通道连续 (c0所有像素, c1所有像素, c2所有像素) mat ncnn.Mat(new_w, target_h, 3) for c in range(3): channel_data data_chw[c].flatten() # H*W for i, val in enumerate(channel_data): mat.channel(c)[i] val # 推理 with net.create_extractor() as ex: ex.input(in0, mat) ret, mat_out ex.extract(out0) output np.array(mat_out) print(f\n输出形状: {output.shape}) print(f 输出格式: (序列长度, 类别数) {output.shape}) # 数据有效性检查 print(f\n数据统计:) print(f 最大值: {np.max(output):.4f}) print(f 最小值: {np.min(output):.4f}) print(f 均值: {np.mean(output):.6f}) print(f 有NaN: {np.isnan(output).any()}) # 检查softmax输出 print(f\n检查输出是否像softmax:) for t in [0, 1, 2]: s output[t, :].sum() print(f t{t}: sum{s:.4f}) # 解码 # 模型输出18710类 (0-18709)字典有18708个字符 (0-18707) # argmax后-1修正原始索引-1后18709变成18708超出字典表示空格 indices np.argmax(output, axis1) indices np.where(indices 0, indices - 1, 0) # -1修正 print(f\n每时间步预测 (argmax, -1修正):) for t in range(min(20, output.shape[0])): idx indices[t] char character[idx] if idx len(character) else ? print(f t{t:2d}: idx{idx:5d}, char{char}) # CTC解码 # -1修正后idx0是blankidx18707表示空格模型输出18708/18709对应空格 def ctc_decode(preds): result [] prev -1 for idx in preds: if idx 0: # blank重置prev prev -1 continue if idx 18707: # 空格位置 if prev ! : result.append( ) prev continue if idx ! prev: result.append(character[idx]) prev idx return result decoded ctc_decode(indices) text .join(decoded) print(f\n识别结果: \{text}\) print(f预期结果: \ROU\) # 非空预测 non_blank [] for t in range(len(indices)): idx indices[t] if idx ! 0 and idx 18707: # 非blank且非空格 non_blank.append((t, character[idx])) if non_blank: print(f\n非空预测: {[(t, c) for t, c in non_blank[:10]]}{... if len(non_blank) 10 else }) print(\n * 60) # if text ROU: # print(✓ 测试通过: 识别结果与预期一致) # else: # print(✗ 测试失败: 识别结果与预期不符) print( * 60)记录至此基本后续在记录量化处理目前的模型输入尺寸w是动态的后面将记录它fp16处理结果

相关新闻

最新新闻

CLONEit 评测以及如何使用CLONEit 轻松传输数据

CLONEit 评测以及如何使用CLONEit 轻松传输数据

如今,手机间传输工具比以往任何时候都更受欢迎,尤其是在升级新设备时。虽然有很多方法可以实现这一点,但 CLONEit 凭借其简单高效而脱颖而出,成为备受欢迎的选择。然而,与任何工具一样,它也有其优缺点。在本…

2026/7/2 23:37:09
Frida Native函数Hook实战:精准获取堆栈、参数与返回值

Frida Native函数Hook实战:精准获取堆栈、参数与返回值

1. 项目概述:为什么我们需要深入Native层?在移动安全逆向和动态分析领域,Frida早已成为从业者手中的“瑞士军刀”。它能让我们在运行时注入JavaScript代码,动态地Hook Java层方法,这解决了很多问题。但当我们面对加固应…

2026/7/2 23:37:09
Trivy漏洞扫描精准配置与修复策略实战指南

Trivy漏洞扫描精准配置与修复策略实战指南

1. 项目概述:为什么你的Trivy扫描结果可能“不准”?最近在几个项目上做安全审计,发现一个挺有意思的现象:不少团队都开始用Trivy做容器镜像和基础设施的漏洞扫描,这绝对是好事。但当我翻看他们的扫描报告和配置时&…

2026/7/2 23:37:09
OAuth2.0授权码模式中CSRF攻击的防御:state参数与PKCE实战指南

OAuth2.0授权码模式中CSRF攻击的防御:state参数与PKCE实战指南

1. 项目概述:OAuth2.0与CSRF的攻防战场在构建现代Web应用时,OAuth2.0几乎成了授权代名词,无论是用微信登录你的新App,还是授权一个第三方工具访问你的GitHub仓库,背后都是它在默默工作。但授权流程的复杂性&#xff0c…

2026/7/2 23:37:09
Web安全基石:CSP内容安全策略原理、部署与实战避坑指南

Web安全基石:CSP内容安全策略原理、部署与实战避坑指南

1. 项目概述:为什么CSP是Web安全的“守门员”?在Web开发的世界里,我们常常把精力花在构建炫酷的功能和流畅的体验上,但安全这道防线,却容易被忽视,直到被攻击的那一天。我见过太多因为一个简单的跨站脚本攻…

2026/7/2 23:37:09
企业级Agent的SOP梳理方法论:从业务流程到Agent工作流的转化

企业级Agent的SOP梳理方法论:从业务流程到Agent工作流的转化

当60%的企业还在Agent试点阶段徘徊时,头部玩家已用一套方法论将落地周期从3个月压缩到3周。本文深度拆解SOP→Agent工作流的转化全链路,附赠可落地的代码模板与选型矩阵。 一、引言:Agent落地的“最后一公里”卡在哪? 2026年初,OpenClaw等开源智能体产品迅速成为市场焦点…

2026/7/2 23:32:09

周新闻

月新闻