C# PaddleInference OCR 验证码识别

news2024/11/15 11:00:08

说明

C# PaddleInference OCR 验证码识别

自己训练的模型,只针对测试图片类型,准确率99%

效果

  

项目

VS2022+.net4.8+OpenCvSharp4+Sdcb.PaddleInference

测试图片

代码

using OpenCvSharp;
using Sdcb.PaddleInference.Native;
using Sdcb.PaddleInference;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace PaddleInference_OCR_验证码识别
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Bitmap bmp;
        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string img = "";
        string startupPath = "";

        OcrShape recShape = new OcrShape(3, 320, 48);
        PaddlePredictor rec_predictor;

        public IReadOnlyList<string> Labels;

        DateTime dt1 = DateTime.Now;
        DateTime dt2 = DateTime.Now;


        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;

            pictureBox1.Image = null;

            img = ofd.FileName;
            bmp = new Bitmap(img);
            pictureBox1.Image = new Bitmap(img);
            textBox1.Text = "";
        }



        private unsafe void Form1_Load(object sender, EventArgs e)
        {

            string startupPath = Application.StartupPath;
            IntPtr det_ptr = PaddleNative.PD_ConfigCreate();
            Encoding PaddleEncoding = Environment.OSVersion.Platform == PlatformID.Win32NT ? Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.ANSICodePage) : Encoding.UTF8;

            //识别模型
            IntPtr rec_ptr = PaddleNative.PD_ConfigCreate();
            String rec_programPath = startupPath + "\\model\\inference.pdmodel";
            String rec_paramsPath = startupPath + "\\model\\inference.pdiparams";
            byte[] rec_programBytes = PaddleEncoding.GetBytes(rec_programPath);
            byte[] rec_paramsBytes = PaddleEncoding.GetBytes(rec_paramsPath);
            fixed (byte* rec_programPtr = rec_programBytes)
            fixed (byte* rec_paramsPtr = rec_paramsBytes)
            {
                PaddleNative.PD_ConfigSetModel(rec_ptr, (IntPtr)rec_programPtr, (IntPtr)rec_paramsPtr);
            }

            rec_predictor = new PaddlePredictor(PaddleNative.PD_PredictorCreate(rec_ptr));

            //Labels
            String labelsPath = startupPath + "\\ppocr_keys.txt";
            Stream Steam = new FileStream(labelsPath, FileMode.Open, FileAccess.Read, FileShare.Read);
            StreamReader reader = new StreamReader(Steam);
            List<string> tempList = new List<string>();
            while (!reader.EndOfStream)
            {
                tempList.Add(reader.ReadLine());
            }
            reader.Dispose();
            Steam.Dispose();
            Labels = tempList;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (pictureBox1.Image == null)
            {
                return;
            }
            dt1 = DateTime.Now;
            var src = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmp);

            int modelHeight = recShape.Height;
            int maxWidth = (int)Math.Ceiling(1.0 * src.Width / src.Height * modelHeight);

            Mat channel3 = new Mat();
            if (src.Channels() == 4)
            {
                channel3 = src.CvtColor(ColorConversionCodes.RGBA2BGR);
            }
            else if (src.Channels() == 3)
            {
                channel3 = src.Clone();
            }
            else if (src.Channels() == 1)
            {
                channel3 = src.CvtColor(ColorConversionCodes.GRAY2RGB);
            }
            else
            {
                throw new Exception("Unexpect src channel: {" + src.Channels() + "}, allow: (1/3/4)");
            }

            Mat resized = ResizePadding(channel3, modelHeight, maxWidth);
            Mat normalize = Normalize(resized);

            using (PaddleTensor input = rec_predictor.GetInputTensor(rec_predictor.InputNames[0]))
            {
                int channel = normalize.Channels();
                input.Shape = new[] { 1, channel, modelHeight, maxWidth };
                float[] data = ExtractMat(normalize, channel, modelHeight, maxWidth);
                input.SetData(data);
            }

            normalize.Dispose();
            resized.Dispose();

            if (!rec_predictor.Run())
            {
                throw new Exception($"PaddlePredictor(Recognizer) run failed.");
            }

            using (PaddleTensor output = rec_predictor.GetOutputTensor(rec_predictor.OutputNames[0]))
            {
                float[] data = output.GetData<float>();
                int[] shape = output.Shape;
                GCHandle dataHandle = default;
                try
                {
                    dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
                    IntPtr dataPtr = dataHandle.AddrOfPinnedObject();

                    int labelCount = shape[2];
                    int charCount = shape[1];

                    StringBuilder sbInfo = new StringBuilder();

                    for (int i = 0; i < shape[0]; i++)
                    {
                        StringBuilder sb = new StringBuilder();
                        int lastIndex = 0;
                        float score = 0;
                        for (int n = 0; n < charCount; ++n)
                        {
                            Mat mat = new Mat(1, labelCount, MatType.CV_32FC1, dataPtr + (n + i * charCount) * labelCount * sizeof(float));
                            int[] maxIdx = new int[2];
                            mat.MinMaxIdx(out double _, out double maxVal, new int[0], maxIdx);
                            if (maxIdx[1] > 0 && (!(n > 0 && maxIdx[1] == lastIndex)))
                            {
                                score += (float)maxVal;
                                sb.Append(GetLabelByIndex(maxIdx[1]));
                            }
                            lastIndex = maxIdx[1];
                            mat.Dispose();
                        }
                        sbInfo.AppendLine("Text:" + sb.ToString());
                        sbInfo.AppendLine("Score:" + score / sb.Length);
                    }

                    dt2 = DateTime.Now;
                    sbInfo.AppendLine("-----------------------------------\n");
                    sbInfo.AppendLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
                    sbInfo.AppendLine("耗时:" + (dt2 - dt1).TotalMilliseconds + "ms\n");
                    textBox1.Text = sbInfo.ToString();
                }
                finally
                {
                    dataHandle.Free();
                }
            }

        }

        string GetLabelByIndex(int x)
        {
            if (x > 0 && x <= Labels.Count)
            {
                return Labels[x - 1];
            }
            else if (x == Labels.Count + 1)
            {
                return "";
            }
            else
            {
                throw new Exception("Unable to GetLabelByIndex: index {" + x + "} out of range {" + Labels.Count + "}, OCR model or labels not matched?");
            }
        }

        private Mat ResizePadding(Mat src, int height, int targetWidth)
        {
            OpenCvSharp.Size size = src.Size();
            float whRatio = 1.0f * size.Width / size.Height;
            int width = (int)Math.Ceiling(height * whRatio);

            if (width == targetWidth)
            {
                return src.Resize(new OpenCvSharp.Size(width, height));
            }
            else
            {
                Mat resized = src.Resize(new OpenCvSharp.Size(width, height));
                return resized.CopyMakeBorder(0, 0, 0, targetWidth - width, BorderTypes.Constant, Scalar.Gray);
            }
        }

        private Mat Normalize(Mat src)
        {
            Mat normalized = new Mat();
            src.ConvertTo(normalized, MatType.CV_32FC3, 1.0 / 255);
            Mat[] bgr = normalized.Split();
            float[] scales = new[] { 1 / 0.229f, 1 / 0.224f, 1 / 0.225f };
            float[] means = new[] { 0.485f, 0.456f, 0.406f };
            for (int i = 0; i < bgr.Length; ++i)
            {
                bgr[i].ConvertTo(bgr[i], MatType.CV_32FC1, 1.0 * scales[i], (0.0 - means[i]) * scales[i]);
            }
            normalized.Dispose();
            Mat dest = new Mat();
            Cv2.Merge(bgr, dest);
            foreach (Mat channel in bgr)
            {
                channel.Dispose();
            }
            return dest;
        }



        private float[] ExtractMat(Mat mat, int channel, int height, int width)
        {
            float[] result = new float[1 * channel * width * height];
            GCHandle resultHandle = GCHandle.Alloc(result, GCHandleType.Pinned);
            IntPtr resultPtr = resultHandle.AddrOfPinnedObject();
            try
            {

                Mat src = mat.Clone();
                if (src.Channels() != channel)
                {
                    throw new Exception($"src channel={src.Channels()}, expected {channel}");
                }
                for (int c = 0; c < channel; ++c)
                {
                    Mat dest = new Mat(height, width, MatType.CV_32FC1, resultPtr + c * height * width * sizeof(float));
                    Cv2.ExtractChannel(src, dest, c);
                    dest.Dispose();
                }
                return result;
            }
            finally
            {
                resultHandle.Free();
            }
        }



        private float[] ExtractMat(Mat[] srcs, int channel, int height, int width)
        {
            float[] result = new float[srcs.Length * channel * width * height];
            GCHandle resultHandle = GCHandle.Alloc(result, GCHandleType.Pinned);
            IntPtr resultPtr = resultHandle.AddrOfPinnedObject();
            try
            {
                for (int i = 0; i < srcs.Length; ++i)
                {
                    Mat src = srcs[i];
                    if (src.Channels() != channel)
                    {
                        throw new Exception($"src[{i}] channel={src.Channels()}, expected {channel}");
                    }
                    for (int c = 0; c < channel; ++c)
                    {
                        Mat dest = new Mat(height, width, MatType.CV_32FC1, resultPtr + (c + i * channel) * height * width * sizeof(float));
                        Cv2.ExtractChannel(src, dest, c);
                        dest.Dispose();
                    }
                }
                return result;
            }
            finally
            {
                resultHandle.Free();
            }
        }

      
    }
}

Demo下载 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/739030.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mac笔记本安装java环境以及idea设置

系列文章目录 文章目录 系列文章目录安装java环境一、安装jdk二、下载安装IntelliJ IDEA三、安装maven四、安装git五、安装tomcat六、安装appenv配置文件七、有关idea的设置1、快捷键设置2、新建类的命名3、字体的大小&#xff0c;有关菜单栏的大小4、框内的tab最多能有多少个窗…

【2 beego学习 - 项目导入与项目知识点】

0 项目导入 1 在英文路径下新建一个同名的项目,拷贝其他数据到这个文件 bee new 同名项目名 cd 同名项目名 go mod tidy go get -u -v github.com/astaxie/beego go get 同名项目名/models2 拷贝部分的项目文件到新目录 bee run 运行的其他错误,按照提示安装文件 1 后端获取…

微软MFC技术中的消息队列及消息处理

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天来聊聊微软MFC技术中的消息队列及消息处理。 MFC应用程序中由Windows 系统以消息的形式发送给应用程序的窗口。窗口接收和处理消息之后&#xff0c;把控制返回给Windows。Windows系统在同一时间可显示多…

HashMap底层原理:数据结构+put()流程+2的n次方+死循环+数据覆盖问题

导航&#xff1a; 【Java笔记踩坑汇总】Java基础进阶JavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线MySQL高级篇设计模式常见面试题源码_vincewm的博客-CSDN博客 目录 一、底层 1.1 HashMap数据结构 1.2 扩容机制 1.3 put()流程 1.4 HashMap是如何计算…

电话号码的字母组合问题

解题思路&#xff1a; 当我第一眼看到这题的时候&#xff0c;我直接举出来一个列子“258”&#xff0c;直接套用多重for循环遍历可以罗列出来&#xff0c;但是根据数字组合的长度不能确定for循环的多少&#xff08;除非把所有for循环个数情况都罗列一遍&#xff09; 所以只能…

几种常用接口调用方式介绍

API&#xff0c;全称叫做Application Programming interface&#xff0c;也就是应用程序接口&#xff0c;API是一些预先定义的函数&#xff0c;我是学Java的&#xff0c;当我要使用这些函数的时候&#xff0c;便可以直接调用Java API&#xff0c;不用去访问源码&#xff0c;也不…

Linux设备驱动程序(四)——调试技术

文章目录 前言一、内核中的调试技术二、通过打印调试1、printk2、重定向控制台消息3、消息如何被记录4、开启及关闭消息5、速度限制6、打印设备编号 三、通过查询调试1、使用 /proc 文件系统①、在/proc中实现文件②、创建自己的 /proc 文件③、seq_file 接口 2、ioctl 方法 四…

Chatbot UI 和 ChatGLM2-6B 的集成

Chatbot UI 和 ChatGLM2-6B 的集成 0. 背景1. 部署 Chatbot UI2. 部署 ChatGLM2-6B3. 修改 ChatGLM2-6B 项目的 openai_api.py4. 修改 Chatbot UI 的配置5. 访问 Chatbot UI 0. 背景 尝试将 Chatbot UI 和 ChatGLM2-6B 的进行集成&#xff0c; ChatGLM2-6B 提供 API 服务&…

精确时钟同步协议ptp/IEEE-1588v2协议-------(2)主从时钟之间的消息交互与时钟同步过程

本文目录 1、主时钟和从时钟之间的消息交互流2、延时delay和偏移offset的计算2.1、延时delay的计算2.2、偏移offset的计算 主时钟和从时钟之间&#xff0c;通过sync, follow up, delay request, delay response这四条消息&#xff0c;完成时钟同步过程。PTP时钟同步系统能工作的…

word绘制横向表格

最近写小论文&#xff0c;表格太宽需要绘制横向表格&#xff0c;找了半天教程说的都不是很详细&#xff0c;我学习了一下决定自己写个教程。 我要在一和二之间创建一个横向表格。首先在一后面添加一个分节符号。布局->分隔符->分节负下一页。 再在二之前添加一个分节符号…

新耀东方|安全狗亮相2023第二届上海网络安全博览会

7月5日至7日&#xff0c;“新耀东方-2023第二届上海网络安全博览会暨高峰论坛”在上海顺利举办。此次大会由上海市信息网络安全管理协会、国家计算机网络应急技术处理协调中心上海分中心、(ISC)2上海分会、上海市普陀区科学技术委员会、上海市网络安全产业示范园共同主办。 作为…

左神算法之中级提升(2)

目录 [案例1】 【题目描述】 【思路解析1】 【思路解析2】 【代码实现】 【案例2】 【题目描述】 【思路解析】 【代码实现】 【案例3】 【题目描述】 【思路解析】 【代码实现】 【案例4】 【题目描述】今日头条2018面试题 第四题 【输入描述】 【思路解析】 【…

对于没有任何基础的初学者,云计算该怎样学习?

想学习任何一门专业技能&#xff0c;可以按下面这一套逻辑梳理&#xff01; 1&#xff09;了解基本内容 云计算这个技术是做什么的&#xff1f;适用哪些场景&#xff1f;有什么优点和缺点&#xff1f; 同时建议先找技术大纲&#xff0c;至少要学哪些技能点&#xff0c;可以网…

Layui之入门

目录 一、layui介绍 1.是什么 2.谁开发的 3.特点 二、layui&#xff0c;easyui和bootstrap的区别 1.layui、easyui与bootstrap的对比 2. layui和bootstrap对比&#xff08;这两个都属于UI渲染框架&#xff09; 3. layui和easyui对比 三、基础使用 四、登录注册实例讲解 …

医院陪诊小程序开发|陪诊小程序定制|陪诊服务app成品

陪诊小程序的功能开发对于陪诊行业有以下好处&#xff1a;   提高服务效率&#xff1a;陪诊小程序可以提供在线预约功能&#xff0c;方便用户随时预约合适的陪诊人员&#xff0c;减少了繁琐的人工沟通和安排工作&#xff0c;提高了服务效率。   增加服务范围&#xff1a;通…

基于matlab将图像标记器多边形转换为标记的块图像以进行语义分割(附源码)

一、前言 此示例演示如何将存储在对象中的多边形标签转换为适用于语义分割工作流的标记阻止图像。 可以使用计算机视觉工具箱中的图像标记器应用来标记太大而无法放入内存和多分辨率图像的图像。有关详细信息&#xff0c;请参阅在图像标记器&#xff08;计算机视觉工具箱&…

uniapp zjy-calendar日历,uni-calendar日历增强版

一、zjy-calendar简介 zjy-calendar日历是对uniapp uni-calendar日历的增强&#xff0c;支持圆点和文字自定义颜色。 二、使用方法 源使用说明&#xff1a;https://uniapp.dcloud.net.cn/component/uniui/uni-calendar.html 1、下载导入 https://ext.dcloud.net.cn/plugin?…

web-php

目录 基础 注释 php程序的组成 php的数据类型 php代码的运行 代码 显示时间 输出账户名和密码 后端对前端的数据进行验证处理代码 连接数据库的代码 前后端代码相结合验证&#xff0c;实现登录接口验证 login.html login.php register.html register.php error…

大模型调用工具魔搭GPT——一键调用魔搭社区上百个AI模型的API

为了让模型开发变得更容易,阿里云在发布会现场推出了一款令开发者耳目一新的工具:ModelScopeGPT(魔搭GPT)。它能够通过担任“中枢模型”的大语言模型一键调用魔搭社区其他的AI模型,实现大模型和小模型协同完成复杂任务。 这类智能调用工具被业界普遍看好。ModelScopeGP…

Android Handler被弃用,那么以后怎么使用Handler,或者类似的功能

Android API30左右&#xff0c;Android应用在使用传统写法使用Handler类的时候会显示删除线&#xff0c;并提示相关的方法已经被弃用&#xff0c;不建议使用。 Handler handler new Handler(){Overridepublic void handleMessage(NonNull Message msg) {super.handleMessage(…