C# PaddleInference OCR 验证码识别

说明

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));//LabelsString 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.hqwc.cn/news/18343.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式——中介者模式

中介者模式&#xff08;非中介者场景&#xff09; 即没有统一的管理者&#xff0c;需要与其他类交流时就new一个 场景 三个类&#xff1a;采购、销售、库存采购商品时&#xff0c;联系销售看看的销售情况好不好&#xff0c;再决定采购的数量销售负责反馈销售情况&#xff0c…

C++教程——const修饰指针、结构体、文件操作

const修饰指针 常量指针 指针常量 const既修饰指针&#xff0c;又修饰常量 指针与数组 结构体 通过指针访问结构体变量中的数据 结构体中const使用场景 文件操作 写文件 读文件 读取数据的方式 二进制读写文件 写文件 读文件

猿人学第二届第一题找修改位置(非答题)

第二届第一题 AES(魔改) Base64(魔改) MD5 第一题不难&#xff0c;想要得到结果直接扣代码就行&#xff0c;但是我想找找到底修改了哪个位置。 MD5( AES (now page) ) AES加密ECB-pksc7 的 key 标准是128位即 16*8(bit) &#xff0c;这里666yuanrenxue66 是15位不是标准k…

ARG DEBIAN_FRONTEND=noninteractive作用说明

使用 在Dockerfile中使用ARG指令定义变量并为其指定一个默认值。ARG指令用于在构建过程中传递变量的值。 对于DEBIAN_FRONTENDnoninteractive&#xff0c;它定义了一个名为DEBIAN_FRONTEND的变量&#xff0c;并将其默认值设置为noninteractive。在这个上下文中&#xff0c;no…

「深度学习之优化算法」(十一)鲸鱼算法

1. 鲸鱼算法简介 (以下描述,均不是学术用语,仅供大家快乐的阅读)   鲸鱼算法(Whale Optimization Algorithm)是根据鲸鱼围捕猎物的行为而提出的算法。鲸鱼是一种群居的哺乳动物,在捕猎时它们也会相互合作对猎物进行驱赶和围捕。鲸鱼算法提出时间并不长,也是一个新兴…

TencentOS3.1安装PHP+Nginx+redis测试系统

PHP和Nginx应用统一安装在/application下。 Nginx选用了较新的版本1.25.0 官网下载安装包&#xff0c;解包。执行如下命令编译&#xff1a; ./configure --prefix/application/nginx-1.25.0 --usernginx --groupnginx --with-http_ssl_module --with-http_stub_status_modu…

Jenkins 创建一个 job , 用于单独执行脚本

目录 1.首先,在Jenkins中创建一个新的job 2.之后&#xff0c;会进入配置页面&#xff0c;在配置页面进行配置。 2.1.找到【Build Steps】在下&#xff0c;拉菜单中选择「シェルの実行」 &#xff08;Shell的运行&#xff09; 2.2.之后&#xff0c;会出现シェルスクリプト …

【Python】Locust持续优化:InfluxDB与Grafana实现数据持久化与可视化分析

在进行性能测试时&#xff0c;我们需要对测试结果进行监控和分析&#xff0c;以便于及时发现问题并进行优化。 Locust在内存中维护了一个时间序列数据结构&#xff0c;用于存储每个事件的统计信息。 这个数据结构允许我们在Charts标签页中查看不同时间点的性能指标&#xff0c…

pytorch LBFGS

LBFGS pytorch的LBFGS也是一个优化器 但是与一般的优化器不同 平常我们的顺序是 losscriterion(predict, gt) optim.zero_grad() loss.backward() optim.step()而LBFGS是 def closure():optim.zero_grad()loss criterion(predict, gt)loss.backward()return lossoptim.step…

小程序自定义海报

如图微信小程序生成海报自定义调整位置 //微信小程序组件 poster.wxml<view styleposition: relative;{{customStyle}};{{painterStyle}}><block wx:if"{{!use2D}}"><canvas canvas-id"photo" style"{{photoStyle}};position: absolut…

QT事件处理

设计一个闹钟&#xff0c;定时播报内容。 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QTimerEvent> #include <QDateTime> #include <QMessageBox> #include <QTextToSpeech> #include <QDebug> namespa…

数据结构与算法——什么是数据结构

当你决定看这篇文章&#xff0c;就意味着系统学习数据结构的开始。下面我们先来讲什么是数据结构。 数据结构&#xff0c;直白地理解&#xff0c;就是研究数据的存储方式。 我们知道&#xff0c;数据存储只有一个目的&#xff0c;即为了方便后期对数据的再利用&#xff0c;就如…