初尝PaddleOCR识别图片中的文字

引言

  • PaddleOCR是一个基于飞桨深度学习框架的OCR工具包,它集成了丰富的文字检测、识别和后处理算法,能够高效、准确地识别出图片中的文字。

说明

  • OpenVINO.NET是一个由开源开发者sdcb发布的,一个个强大的工具集,通过优化神经网络和加速推理,帮助他们快速构建高性能的机器学习和计算机视觉应用。
  • PaddleOCR 旨在打造一套丰富、领先、且实用的 OCR 工具库,助力开发者训练出更好的模型,并应用落地。
 <Grid>
     <Grid.RowDefinitions>
         <RowDefinition Height="50"></RowDefinition>
         <RowDefinition></RowDefinition>
     </Grid.RowDefinitions>
     <Grid.ColumnDefinitions>
         <ColumnDefinition></ColumnDefinition>
         <ColumnDefinition></ColumnDefinition>
     </Grid.ColumnDefinitions>
     <!--添加两个按钮,分别设置打开图片和打开文本-->
     <Button Grid.Row="0" Grid.Column="0" x:Name="btnOpenImage" Content="打开图片" Background="Blue" Foreground="White" Width="100" Height="40" HorizontalAlignment="Right" VerticalAlignment="Center" Click="btnDialog_Click"/>
     <Button Grid.Row="0" Grid.Column="1"  x:Name="btnOcrTxt" Content="立即识别" Background="Green" Foreground="White" Width="100" Height="40" Margin="10,0" HorizontalAlignment="Left" VerticalAlignment="Center" Click="btnOrc_Click"/>

     <!--添加两个边框 显示默认显示,打开后显示对应效果-->
     <Border Grid.Row="1" Grid.Column="0" Margin="10,10"  BorderBrush="Gray" BorderThickness="1">
         <Image x:Name="myImage"  Stretch="Fill"></Image>
     </Border>

     <ScrollViewer Grid.Row="1" Grid.Column="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
         <Border  Margin="10,10"  BorderBrush="Gray" BorderThickness="1">
             <TextBlock x:Name="myText" TextWrapping="Wrap"  Margin="0,10,0,0"  FontSize="18" />
         </Border>
     </ScrollViewer>
  
 </Grid>
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : System.Windows.Window
{
    private  string ImagePath=string.Empty;
    private Bitmap ImageInfo =null;
    private string pattern = @"[\u4e00-\u9fa50-9a-zA-Z]+";
    public MainWindow()
    {
        InitializeComponent();
        Settings.GlobalModelDirectory = System.IO.Path.Combine("D:\\WpfOcrApp\\Models");

    }
    private void btnDialog_Click(object sender, RoutedEventArgs e)
    {
        Button btnUpload = (Button)sender;
        OpenFileDialog openFileDialog = new OpenFileDialog
        {
            Filter = "Image files (*.jpg;*.png;*.jpeg)|*.jpg;*.png;*.jpeg",
            Title = btnUpload.Name.Equals("btnOpenImage", StringComparison.OrdinalIgnoreCase) ? "选择图片" : "选择TXT文件"
        };
        bool? result = openFileDialog.ShowDialog();
        if (result == true)
        {
            string filePath = openFileDialog.FileName;
            ImagePath = filePath;
            if (!string.IsNullOrWhiteSpace(filePath))
            {
                using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    // 创建一个BitmapImage对象并设置其StreamSource为FileStream  
                    BitmapImage bitmapImage = new BitmapImage();
                    bitmapImage.BeginInit();
                    bitmapImage.StreamSource = stream;
                    bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                    bitmapImage.EndInit();
                    ImageInfo = new Bitmap(stream);
                    // 确保Stream在BitmapImage使用之后被关闭  
                    stream.Close();
                    // 将BitmapImage对象设置为Image控件的Source  
                    myImage.Source = bitmapImage;
                }

            }
        }
    }

    private void btnOrc_Click(object sender, RoutedEventArgs e)
    {
        if (string.IsNullOrWhiteSpace(ImagePath))
        {
            myText.Text = $"请先选择图片";
            return;
        }
       OrcResult();

    }

    private void OrcResult()
    {
       // 如何模型不存在,则会自动下载,如果wpf 出现下载不下来,可以把这段代码在控制台上执行下载
        FullOcrModel fullOcrModel = OnlineFullModels.ChineseServerV4.DownloadAsync().GetAwaiter().GetResult();
        Mat src = Cv2.ImRead(@$"{ImagePath}");
        // 注意 使用CUP 最好设置一下DetectionStaticSize和RecognitionStaticWidth这两个参数
        // GPU 默认就设置了
        using (PaddleOcrAll all = new(fullOcrModel, new PaddleOcrOptions(new Sdcb.OpenVINO.DeviceOptions("CPU")) 
        {
            DetectionStaticSize = new OpenCvSharp.Size(1024, 1024),
            RecognitionStaticWidth = 512
        })
        {
            AllowRotateDetection = true,
            Enable180Classification = true,
        })
        {
            StringBuilder builder = new StringBuilder();
            Stopwatch sw = Stopwatch.StartNew();
            PaddleOcrResult result = all.Run(src);
            builder.AppendLine($"总耗时:{sw.ElapsedMilliseconds} ms");
            string strText = result.Text;
            List<string> strings = strText.Split('\n').ToList();
            foreach (var item in strings)
            {
                bool isMatch = Regex.IsMatch(item, pattern);
                if (isMatch)
                    builder.AppendLine(item);
            }

            using (Graphics g = Graphics.FromImage(ImageInfo))
            {
                foreach (PaddleOcrResultRegion region in result.Regions)
                {
                    // 设置线条的样式(如颜色、粗细等)  
                    System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Brushes.Red, 2);
                    bool isMatch = Regex.IsMatch(region.Text, pattern);
                    if (isMatch)
                        g.DrawRectangle(pen, region.Rect.BoundingRect().Left, region.Rect.BoundingRect().Top, region.Rect.BoundingRect().Width, region.Rect.BoundingRect().Height);
                    //builder.AppendLine($"Text: {region.Text}, Score: {region.Score}, RectCenter: {region.Rect.Center}, RectSize:    {region.Rect.Size}, Angle: {region.Rect.Angle}");

                }
            }

            myText.Text = builder.ToString();
            using (MemoryStream memory = new MemoryStream())
            {
                ImageInfo.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
                memory.Position = 0;
                // 创建一个BitmapImage对象并设置其StreamSource为FileStream  
                BitmapImage bitmapImage = new BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage.StreamSource = memory;
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapImage.EndInit();
                // 确保Stream在BitmapImage使用之后被关闭  
                memory.Close();
                // 将BitmapImage对象设置为Image控件的Source  
                myImage.Source = bitmapImage;

            }
        }

    }
}

上述代码运行效果如下:
识别效果

参考

  • https://github.com/sdcb/OpenVINO.NET
  • https://github.com/paddlepaddle/PaddleOCR

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

科普文:Linux服务器性能调优概叙

概叙 Java web应用性能分析之服务端慢和优化概叙_cpu飙高java-CSDN博客 Java web应用性能分析之【CPU飙升分析概述】_web页面性能分析cpu占满是因为死循环,还是循环过多-CSDN博客 在我们的软件服务中&#xff0c;软件部署的服务器&#xff0c;一般都是linux服务器&#xff0c…

【每天学会一个渗透测试工具】SQLmap安装教程及使用

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 ✨SQLmap简介 Sqlmap是一款开源的渗透测试工具 &#x1f680;下载及安装 下载地址&#xff1a;http://sqlmap.org/ windo…

两个Activity之间切换时UI部分重叠

书籍 《第一行代码 Android》第三版 开发 环境 Android Studio Jellyfish | 2023.3.1 setContentView android studio自动生成的SecondActivity.kt中自动生成的代码中已经绑定了second_layout.xml的布局资源&#xff0c;通过代码&#xff1a;setContentView(R.layout.secon…

windows@资源管理器中的地址栏@访问共享文件夹的各种方法@管理共享文件夹

文章目录 资源管理器中的地址栏可以访问什么访问共享文件夹&#x1f47a;UNC路径资源管理器打开共享文件夹纯命令行方式访问共享文件夹 共享文件夹相关操作查看所有已经共享的文件夹&#x1f47a;停止某个文件的共享 共享文件夹的访问控制补充匿名访问问题&#x1f60a;强制启用…

【Linux】高级IO——五种IO模型和基本概念 ,非阻塞IO,fcntl,实现非阻塞IO,同步通信和异步通信

文章目录 Linux高级IO1. 五种IO模型1.1 阻塞IO1.2 非阻塞IO1.3 信号驱动IO1.4 IO多路转接1.5 异步IO 2. 同步通信和异步通信3. 阻塞和非阻塞 Linux高级IO 1. 五种IO模型 IO是什么&#xff1f; IO是计算机领域中的缩写&#xff0c;指的是输入/输出&#xff08;Input/Output&…

【vue3|第15期】Vue3模板语法入门指南

日期:2024年7月2日 作者:Commas 签名:(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释:如果您觉得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方,还望各位大佬不吝赐教,谢谢^ - ^ 1.01365 = 37.7834;0.99365 = 0.0255 1.02365 = 1377.4083…

上海网站建设如何做

上海是中国最繁华的城市之一&#xff0c;作为全国的经济、文化和科技中心&#xff0c;网站建设在上海变得越来越重要。如何做好上海网站建设&#xff0c;让网站更加吸引人&#xff0c;成为企业和个人宣传自身的重要平台呢&#xff1f; 首先&#xff0c;要有清晰的定位和目标。在…

IT之旅启航:高考后IT专业预习全攻略

✨作者主页&#xff1a; Mr.Zwq✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01; 您的点赞、关注、收藏、评论&#xff0c;是对我最大…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【密钥生成介绍及算法规格】

密钥生成介绍及算法规格 当业务需要使用HUKS生成随机密钥&#xff0c;并由HUKS进行安全保存时&#xff0c;可以调用HUKS的接口生成密钥。 注意&#xff1a; 密钥别名中禁止包含个人数据等敏感信息。 开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin/harm…

Java实现电子围栏的小例子

主要需求是实现一个电子围栏判断的小例子其中包括前端和后端的demo代码 引入对应的依赖库 <!--jts库通常用于几何计算和表示地理空间数据--> <dependency><groupId>org.locationtech.jts</groupId><artifactId>jts-core</artifactId><…

web学习笔记(七十五)

目录 1.小程序修改响应式数据 1.1修改基本数据类型的值 1.2修改复合数据类型的值 2. 发送请求 3.小程序解决跨域问题 1.小程序修改响应式数据 1.1修改基本数据类型的值 在小程序中需要先将data中的数据拿过来并结构&#xff0c;才可以在this.setdata中修改数据&#xf…

2024攻防演练:亚信安全推出MSS/SaaS短期定制服务

随着2024年攻防演练周期延长的消息不断传出&#xff0c;各参与方将面临前所未有的挑战。面对强大的攻击队伍和日益严格的监管压力&#xff0c;防守单位必须提前进行全面而周密的准备和部署。为应对这一形势&#xff0c;亚信安全特别推出了为期三个月的MSS/SaaS短期订阅方案。该…

SpringBoot Task 定时任务

springboot中使用Task定时任务非常简单 springboot 中自带的都有注解不需要引入依赖 第一步&#xff1a;在启动类上添加启用定时任务注解 EnableScheduling //开启任务调度 第二步&#xff1a;创建一个springboot组件用于定时任务管理 package cn.lsy.api.Task;import cn.ls…

【LeetCode】十一、滑动窗口:长度最小的子数组 + 定长子串的元音最大数目

文章目录 1、滑动窗口2、leetcode209&#xff1a;长度最小的子数组3、leetcode1456&#xff1a;定长子串中元音的最大数目 1、滑动窗口 如下&#xff0c;有一个数组&#xff0c;现三个元素为一组&#xff0c;求最大的和&#xff0c;自然可以while循环实现&#xff1a;i 、i1、…

着色器预热?为什么 Flutter 需要?为什么原生 App 不需要?那 Compose 呢?Impeller 呢?

依旧是来自网友的问题&#xff0c;这个问题在一定程度上还是很意思的&#xff0c;因为大家可能会想&#xff0c;Flutter 使用 skia&#xff0c;原生 App 是用 skia &#xff0c;那为什么在 Flutter 上会有着色器预热&#xff08;Shader Warmup&#xff09;这样的说法&#xff1…

使用getline()从文件中读取一行字符串

我们知道&#xff0c;getline() 方法定义在 istream 类中&#xff0c;而 fstream 和 ifstream 类继承自 istream 类&#xff0c;因此 fstream 和 ifstream 的类对象可以调用 getline() 成员方法。 当文件流对象调用 getline() 方法时&#xff0c;该方法的功能就变成了从指定文件…

lnternet 发展史

一&#xff0c;lnternet 发展史 ARPA net &#xff08;上世纪50年代二战结束&#xff09; 无线 战场指挥通信协议落后 TCP/IP 包交换 WEB (70年代 ) 80年代 90年代 二&#xff0c;互联网的典型应用&#xff1a; 96年到2008年 第一代技术…

8.ApplicationContext常见实现

ClassPathXmlApplicationContext 基于classpath下xml格式的配置文件来创建 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-i…

Linux-页表如何对物理内存进行映射

1.1 页框和页帧 我们知道通过页表可以将虚拟内存映射到对应的物理内存&#xff0c;而操作系统对于物理内存的管理并不是以字节为单位的&#xff0c;而是将物理内存分为许多大小为4KB的块&#xff0c;称为页框或页帧&#xff0c;这就是为什么我们在创建共享内存是建议将大小设定…

【server】3、注册中心与配置中心

1、服务注册与发现 1.1、consul 1.1.1 是什么 官网&#xff1a; Consul by HashiCorp spring-cloud-consul: Spring Cloud Consul :: Spring Cloud Consul gitHub 官网 &#xff1a;GitHub - hashicorp/consul: Consul is a distributed, highly available, and data cent…