news 2026/10/30 12:53:05

免费GPU版OCR推理库来了!不挑卡的OnnxRuntime DML方案来了

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
免费GPU版OCR推理库来了!不挑卡的OnnxRuntime DML方案来了

无论你是N卡、A卡还是集成显卡,现在都能跑出高效的OCR识别效果!

效果

测试项目

跨显卡的OCR痛点

在OCR模型部署的实际应用中,开发者常常面临这样的困境:

训练时用的N卡,部署环境却是A卡

客户机器只有集成显卡,GPU加速无法使用

不同型号显卡需要不同的推理后端配置

CUDA依赖导致部署环境复杂

特别是对于中小型开发团队或个人开发者,为每一类显卡维护不同的推理方案成本实在太高。

DML:微软的跨显卡解决方案

DirectML(Direct Machine Learning)是微软推出的高性能硬件加速DirectX 12库,它最大的优势就是 跨厂商显卡支持:

✅ 支持NVIDIA、AMD、Intel全系列显卡

✅ 无需额外安装CUDA或ROCm环境

✅ 直接使用Windows原生图形接口

✅ 性能接近专用AI推理框架

我们的OCR推理库正是基于OnnxRuntime的DML执行提供程序构建,这意味着只要你的Windows机器有DirectX 12兼容的显卡,就能享受GPU加速的OCR识别!

API接口

//ocr 初始化 extern "C" _declspec(dllexport) int __cdecl init(void** engine , bool use_gpu , int gpu_id , char* det_model_dir , int limit_side_len , double det_db_thresh , double det_db_box_thresh , double det_db_unclip_ratio , bool use_dilation , bool cls , bool use_angle_cls , char* cls_model_dir , double cls_thresh , double cls_batch_num , char* rec_model_dir , char* rec_char_dict_path , int rec_batch_num , int rec_img_h , int rec_img_w , int rec_predictor_num , char* msg); //识别 extern "C" _declspec(dllexport) int __cdecl ocr(void* engine, Mat* image, char* msg, char** ocr_result, int* ocr_result_len); //释放 extern "C" _declspec(dllexport) int __cdecl destroy(void* engine, char* msg);

C#调用案例

using Newtonsoft.Json; using OpenCvSharp; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; namespace OCRV5Test { public partial class Form1 : Form { public Form1() { InitializeComponent(); } const string DllName = "lw.OnnxRuntime.PPOCRSharp_dml.dll"; //初始化 [DllImport(DllName, EntryPoint = "init", CallingConvention = CallingConvention.Cdecl)] public extern static int init(ref IntPtr engine , bool use_gpu , int gpu_id , string det_model_dir , int limit_side_len , double det_db_thresh , double det_db_box_thresh , double det_db_unclip_ratio , bool use_dilation , bool cls , bool use_angle_cls , string cls_model_dir , double cls_thresh , double cls_batch_num , string rec_model_dir , string rec_char_dict_path , int rec_batch_num , int rec_img_h , int rec_img_w , int predictor_num , StringBuilder msg); //识别 [DllImport(DllName, EntryPoint = "ocr", CallingConvention = CallingConvention.Cdecl)] public extern static int ocr(IntPtr engine, IntPtr image, StringBuilder msg, out IntPtr ocr_result, out int ocr_result_len); //释放 [DllImport(DllName, EntryPoint = "destroy", CallingConvention = CallingConvention.Cdecl)] public extern static int destroy(IntPtr engine, StringBuilder msg); static IntPtr OCREngine; private Bitmap bmp; private String imgPath = null; private List<OCRResult> ltOCRResult; private string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tif;*.png"; private StringBuilder OCRResultInfo = new StringBuilder(); private StringBuilder OCRResultAllInfo = new StringBuilder(); Pen pen = new Pen(Brushes.Red, 2f); /// <summary> /// 选择图片 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = fileFilter; if (ofd.ShowDialog() == DialogResult.OK) { imgPath = ofd.FileName; bmp = new Bitmap(imgPath); pictureBox1.Image = bmp; richTextBox1.Clear(); button2_Click(null, null); } } /// <summary> /// 识别 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) { if (OCREngine == IntPtr.Zero) { MessageBox.Show("请先初始化!!!"); return; } if (imgPath == null) { MessageBox.Show("请先选择图片!!!"); return; } button1.Enabled = false; button2.Enabled = false; richTextBox1.Clear(); OCRResultInfo.Clear(); OCRResultAllInfo.Clear(); Application.DoEvents(); Mat img = new Mat(imgPath); StringBuilder msgTemp = new StringBuilder(128); StringBuilder ocrResultStr = new StringBuilder(1024 * 100); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); IntPtr strPtr; int ocr_result_len = 0; int res = ocr(OCREngine, img.CvPtr, msgTemp, out strPtr, out ocr_result_len); img.Dispose(); byte[] buffer = new byte[ocr_result_len]; Marshal.Copy(strPtr, buffer, 0, ocr_result_len); string ocr_result = Encoding.UTF8.GetString(buffer); Marshal.FreeCoTaskMem(strPtr); stopwatch.Stop(); double totalTime = stopwatch.Elapsed.TotalMilliseconds; OCRResultAllInfo.AppendLine($"耗时: {totalTime:F2}ms"); OCRResultAllInfo.AppendLine("---------------------------"); OCRResultInfo.AppendLine($"耗时: {totalTime:F2}ms"); OCRResultInfo.AppendLine("---------------------------"); if (res == 0) { ltOCRResult = Newtonsoft.Json.JsonConvert.DeserializeObject<List<OCRResult>>(ocr_result); OCRResultAllInfo.Append(JsonConvert.SerializeObject(ltOCRResult, Newtonsoft.Json.Formatting.Indented)); Graphics graphics = Graphics.FromImage(bmp); foreach (OCRResult item in ltOCRResult) { OCRResultInfo.AppendLine(item.text); System.Drawing.Point[] pt = new System.Drawing.Point[] { new System.Drawing.Point(item.x1, item.y1) , new System.Drawing.Point(item.x2, item.y2) , new System.Drawing.Point(item.x3, item.y3) , new System.Drawing.Point(item.x4, item.y4) }; graphics.DrawPolygon(pen, pt); } graphics.Dispose(); if (checkBox1.Checked) { richTextBox1.Text = OCRResultAllInfo.ToString(); } else { richTextBox1.Text = OCRResultInfo.ToString(); } pictureBox1.Image = null; pictureBox1.Image = bmp; } else { MessageBox.Show("识别失败," + msgTemp.ToString()); } img.Release(); button1.Enabled = true; button2.Enabled = true; } /// <summary> /// 初始化 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_Load(object sender, EventArgs e) { rdomobile.Checked = true; chkcls.Checked = false; chkuse_gpu.Checked = true; txtgpu_id.Text = "1"; } private void checkBox1_CheckedChanged(object sender, EventArgs e) { richTextBox1.Clear(); if (checkBox1.Checked) { richTextBox1.Text = OCRResultAllInfo.ToString(); } else { richTextBox1.Text = OCRResultInfo.ToString(); } } private void radioButton1_CheckedChanged(object sender, EventArgs e) { RadioButton rb = sender as RadioButton; } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { UnloadModel(); } private void btnDestroy_Click(object sender, EventArgs e) { UnloadModel(); } void UnloadModel() { if (OCREngine != IntPtr.Zero) { StringBuilder msgTemp = new StringBuilder(128); destroy(OCREngine, msgTemp); Console.WriteLine("释放成功:" + msgTemp.ToString()); OCREngine = IntPtr.Zero; } } private void btnInit_Click(object sender, EventArgs e) { if (OCREngine != IntPtr.Zero) { StringBuilder msgTemp = new StringBuilder(128); destroy(OCREngine, msgTemp); Console.WriteLine("释放成功:" + msgTemp.ToString()); OCREngine = IntPtr.Zero; LoadModel(); } else { LoadModel(); } } void LoadModel() { StringBuilder msgTemp = new StringBuilder(128); string root_dir = Application.StartupPath + @"\inference"; bool use_gpu = true; int gpu_id = 0; string det_model_dir = ""; int limit_side_len = 960; double det_db_thresh = 0.3; double det_db_box_thresh = 0.6; double det_db_unclip_ratio = 1.2; bool use_dilation = false; bool cls = true; bool use_angle_cls = true; string cls_model_dir = ""; double cls_thresh = 0.9; int cls_batch_num = 1; string rec_model_dir = ""; string rec_char_dict_path = "inference/ppocrv5_dict.txt"; int rec_batch_num = 8; int rec_img_h = 48; int rec_img_w = 320; int predictor_num = 4; //赋值 if (chkuse_gpu.Checked == true) { use_gpu = true; } else { use_gpu = false; } gpu_id = Convert.ToInt32(txtgpu_id.Text.ToString()); det_db_thresh = Convert.ToDouble(txtdet_db_thresh.Text.ToString()); det_db_box_thresh = Convert.ToDouble(txtdet_db_box_thresh.Text.ToString()); det_db_unclip_ratio = Convert.ToDouble(txtdet_db_unclip_ratio.Text.ToString()); if (chkcls.Checked == true) { cls = true; } else { cls = false; } cls_batch_num = Convert.ToInt32(txtcls_batch_num.Text.ToString()); rec_batch_num = Convert.ToInt32(txtrec_batch_num.Text.ToString()); predictor_num = Convert.ToInt32(txtpredictor_num.Text.ToString()); if (rdomobile.Checked) { det_model_dir = "inference/PP-OCRv5_mobile_det_onnx.onnx"; rec_model_dir = "inference/PP-OCRv5_mobile_rec_onnx.onnx"; cls_model_dir = "inference/PP-OCRv5_mobile_cls_onnx.onnx"; } else { det_model_dir = "inference/PP-OCRv5_server_det_infer.onnx"; rec_model_dir = "inference/PP-OCRv5_server_rec_infer.onnx"; cls_model_dir = "inference/PP-OCRv5_server_cls_infer.onnx"; } int res = init(ref OCREngine , use_gpu , gpu_id , det_model_dir , limit_side_len , det_db_thresh , det_db_box_thresh , det_db_unclip_ratio , use_dilation , cls , use_angle_cls , cls_model_dir , cls_thresh , cls_batch_num , rec_model_dir , rec_char_dict_path , rec_batch_num , rec_img_h , rec_img_w , predictor_num , msgTemp); if (res == 0) { Console.WriteLine("模型加载成功!"); } else { string msg = msgTemp.ToString(); Console.WriteLine("模型加载失败," + msg); } } } }

下载

通过网盘分享的文件:lw.OnnxRuntime.PPOCRSharp_dml_test.rar 链接: https://pan.baidu.com/s/188r8psLROddGQrCxglyBIQ?pwd=cs37 提取码: cs37

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/29 15:06:18

ncm文件高效处理指南:从问题诊断到自动化解决方案

ncm文件高效处理指南&#xff1a;从问题诊断到自动化解决方案 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 一、问题分析&#xff1a;ncm格式处理的现实挑战 在数字化音频管理领域&#xff0c;ncm格式作为一种加密音频格式&#…

作者头像 李华
网站建设 2026/10/30 11:36:17

SDXL 1.0电影级绘图工坊入门指南:从安装到生成第一张电影级图像

SDXL 1.0电影级绘图工坊入门指南&#xff1a;从安装到生成第一张电影级图像 1. 为什么这款工具值得你花10分钟上手&#xff1f; 你是不是也遇到过这些问题&#xff1a; 下载了SDXL模型&#xff0c;却卡在环境配置、依赖冲突、显存报错的死循环里&#xff1f;看了一堆WebUI教…

作者头像 李华
网站建设 2026/10/28 16:55:27

突破单平台限制:7个高效策略实现多平台直播分发

突破单平台限制&#xff1a;7个高效策略实现多平台直播分发 【免费下载链接】obs-multi-rtmp OBS複数サイト同時配信プラグイン 项目地址: https://gitcode.com/gh_mirrors/ob/obs-multi-rtmp 您是否正在寻找提升直播分发效率的解决方案&#xff1f;OBS Multi RTMP插件正…

作者头像 李华
网站建设 2026/10/30 3:27:25

ncmdump完全指南:从入门到精通的3种实用技巧

ncmdump完全指南&#xff1a;从入门到精通的3种实用技巧 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump ncmdump是一款专注于网易云音乐NCM格式解密的工具&#xff0c;能够帮助用户将加密的音乐文件转换为通用的MP3格式&#xff0c;…

作者头像 李华
网站建设 2026/10/28 17:03:24

YOLO12实时推理优化:FlashAttention加速技巧大揭秘

YOLO12实时推理优化&#xff1a;FlashAttention加速技巧大揭秘 1. 为什么YOLO12的FlashAttention值得深挖&#xff1f; 你可能已经注意到&#xff0c;YOLO12镜像启动后&#xff0c;Web界面顶部状态栏显示“ 模型已就绪”&#xff0c;点击检测按钮几乎秒出结果——但你知道这背…

作者头像 李华
网站建设 2026/10/30 17:04:13

揭秘Krita-AI-Diffusion控制层失效:Clip Vision模型修复全指南

揭秘Krita-AI-Diffusion控制层失效&#xff1a;Clip Vision模型修复全指南 【免费下载链接】krita-ai-diffusion Streamlined interface for generating images with AI in Krita. Inpaint and outpaint with optional text prompt, no tweaking required. 项目地址: https:/…

作者头像 李华