C# PaddleInference OCR文字识别(只识别)

说明

C# PaddleInference OCR文字识别(只识别),没有文字区域检测、文字方向判断

测试图片是文字区域检测裁剪出来、处理过的图片

完整的OCR识别查看 C# PaddleInference OCR识别 学习研究Demo_天天代码码天天的博客-CSDN博客

效果

项目

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

 测试图片

 代码

using OpenCvSharp;
using Sdcb.PaddleInference;
using Sdcb.PaddleInference.Native;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
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 + "\\ch_PP-OCRv3_rec\\inference.pdmodel";String rec_paramsPath = startupPath + "\\ch_PP-OCRv3_rec\\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();}}}
}

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

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

相关文章

idea集成maven-mvnd

maven-mvnd是什么&#xff1f; 参考文档&#xff1a; Maven加强版 — mvnd的使用测试 - 知乎https://blog.csdn.net/cr898839618/article/details/122319874 1.下载mvnd安装包 Releases apache/maven-mvnd GitHub 2.修改配置文件&#xff1a;安装包中的conf目录下的mvnd.…

C++之函数模板高级用法(一百五十四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

rabbitmq使用springboot实现direct模式

一、 Direct模式 类型&#xff1a;direct特点&#xff1a;Direct模式是fanout模式上的一种叠加&#xff0c;增加了路由RoutingKey的模式。 二、coding Ⅰ 生产者 1、引入相应的pom文件 pom.xml <?xml version"1.0" encoding"UTF-8"?> <pro…

四十三、贪心——Huffman树、排序不等式

算法主要内容 一、Huffman树1、题目内容——合并果子2、算法思路&#xff08;1&#xff09;“合并果子”中的Huffman树&#xff08;2&#xff09;算法步骤&#xff08;3&#xff09;状态转移 3、题解 二、排序不等式1、题目内容——排队打水2、算法思路&#xff08;1&#xff0…

科研论文中SCI,SSCI ,CSSCI是什么

目录 1 SCI 2 SSCI 3 CSSCI 什么是SCI&#xff0c;SSCI &#xff0c;CSSCI 目前&#xff0c;在国际科学界&#xff0c;如何正确评价基础科学研究成果已引起越来越广泛的关注。而被SCI、SSCI收录的科技论文的多寡则被看作衡量一个国家的基础科学研究水平、科技实力和科技论文水平…

STM32——关于时钟源的实际使用及解释

1、STM32内部有5个时钟源&#xff0c;分别为HSI、HSE、LSE、LSI、PLL。 HSE&#xff1a;高速外部时钟&#xff0c;可接石英谐振器、陶瓷谐振器&#xff0c;或者接外部时钟源&#xff0c;其频率范围为4MHZ~16MHZ。 LSE&#xff1a; 低速外部时钟&#xff0c;接频率为32.768KHZ…

基于深度学习的高精度Caltech行人检测系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度Caltech数据集行人检测识别系统可用于日常生活中或野外来检测与定位行人目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的行人目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv…

电源频率检测器/采用555时基电路的过流检测器电路设计

电源频率检测器 对于某些电子仪器和电气设备&#xff0c;对见六电源的频率有着一定的要求&#xff0c;电源频率高于或低于 50Hz&#xff0c;都会影响设备的正常工作&#xff0c;甚至造成仪器和设备的损坏。因此&#xff0c;对于此类设备需要装设电源频率检测装置&#xff0c;当…

软件工程师,学习下JavaScript ES6新特性吧

概述 作为一名软件工程师&#xff0c;不管你是不是前端开发的岗位&#xff0c;工作中或多或少都会用到一点JavaScript。JavaScript是大家所了解的语言名称&#xff0c;但是这个语言名称是Oracle公司注册的商标。JavaScript的正式名称是ECMAScript。1996年11月&#xff0c;JavaS…

【后端面经-Java】I/O多路复用 简录

【后端面经-Java】I/O多路复用 简录 0. Java 线程IO模型1. BIO2. NIO3. I/O多路复用&#xff08;主要&#xff09;3.1 概念3.2 实现1. select2. poll3. epoll 4. AIO5. 技术对比5.1 BIO、NIO、I/O多路复用、AIO对比5.2 select、poll、epoll对比 6. 面试模拟参考资料 0. Java 线…

我国新能源汽车存量已突破1620万辆,登记数量创历史新高

根据公安部发布的最新数据&#xff0c;截至2023年6月底&#xff0c;全国的机动车数量达到4.26亿辆&#xff0c;其中汽车数量为3.28亿辆&#xff0c;新能源汽车数量为1620万辆。与此同时&#xff0c;机动车驾驶人口达到5.13亿人&#xff0c;其中汽车驾驶人口为4.75亿人。在2023年…

从C语言到C++_25(树的十道OJ题)力扣:606+102+107+236+426+105+106+144+94+145

目录 606. 根据二叉树创建字符串 - 力扣&#xff08;LeetCode&#xff09; 解析代码&#xff1a; 102. 二叉树的层序遍历 - 力扣&#xff08;LeetCode&#xff09; 解析代码&#xff1a; 107. 二叉树的层序遍历 II - 力扣&#xff08;LeetCode&#xff09; 解析代码&…