news 2026/9/3 3:23:28

免费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/9/2 21:06:37

YOLO12开箱评测:80类物体检测效果惊艳展示

YOLO12开箱评测&#xff1a;80类物体检测效果惊艳展示 目标检测模型的进化从未停歇。当YOLO系列走到第十二代&#xff0c;它不再只是“又一个升级版”——而是从底层架构开始重写的一次真正跃迁。YOLO12不是在YOLOv11基础上微调参数&#xff0c;而是用一套全新的注意力为中心架…

作者头像 李华
网站建设 2026/9/2 7:54:34

深入解析Spock框架下的异步测试

在使用Spock框架进行单元测试时,特别是涉及到异步操作和文件系统交互的场景,测试的设计和配置需要特别小心。最近,我在测试一个Spring应用时遇到了一些有趣的问题。让我们通过这个博客详细探讨一下如何解决这些问题。 背景介绍 我的测试目标是验证一个SimulationStorageSe…

作者头像 李华
网站建设 2026/9/2 22:01:08

小白必看:Qwen3-ForcedAligner-0.6B语音对齐模型一键部署教程

小白必看&#xff1a;Qwen3-ForcedAligner-0.6B语音对齐模型一键部署教程 你是否遇到过这些情况&#xff1a; 录了一段5分钟的课程讲解&#xff0c;想自动标出每句话开始的时间点&#xff1f;做双语字幕时&#xff0c;需要把中文文本和英文音频逐字对齐&#xff0c;手动拖进度…

作者头像 李华
网站建设 2026/9/2 22:01:12

3个黑科技让你的LOL操作快人一步:英雄联盟辅助工具使用指南

3个黑科技让你的LOL操作快人一步&#xff1a;英雄联盟辅助工具使用指南 【免费下载链接】LeagueAkari ✨兴趣使然的&#xff0c;功能全面的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/LeagueAkari 还在…

作者头像 李华
网站建设 2026/9/2 21:59:44

FakeLocation黑科技:让手机定位随心所欲的隐藏技巧

FakeLocation黑科技&#xff1a;让手机定位随心所欲的隐藏技巧 【免费下载链接】FakeLocation Xposed module to mock locations per app. 项目地址: https://gitcode.com/gh_mirrors/fak/FakeLocation 还在为APP强制获取真实位置烦恼吗&#xff1f;想在社交平台"假…

作者头像 李华