C# PaddleInference 文字检测(只检测不识别)

news2024/12/26 11:21:49

效果

 项目

Demo下载

代码

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

namespace PaddleInference_文字检测
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

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

        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);
        }


        int MaxSize = 1536;
        float? BoxThreshold = 0.3f;
        float? BoxScoreThreahold = 0.7f;
        int? DilatedSize = 2;
        int MinSize = 3;
        float UnclipRatio = 2.0f;
        PaddlePredictor predictor;
        private unsafe void Form1_Load(object sender, EventArgs e)
        {
            IntPtr _ptr = PaddleNative.PD_ConfigCreate();

            Encoding PaddleEncoding = Environment.OSVersion.Platform == PlatformID.Win32NT ? Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.ANSICodePage) : Encoding.UTF8;

            //设置推理模型路径
            String programPath = Application.StartupPath + "\\ch_PP-OCRv3_det\\inference.pdmodel";
            String paramsPath = Application.StartupPath + "\\ch_PP-OCRv3_det\\inference.pdiparams";

            byte[] programBytes = PaddleEncoding.GetBytes(programPath);
            byte[] paramsBytes = PaddleEncoding.GetBytes(paramsPath);
            fixed (byte* programPtr = programBytes)
            fixed (byte* paramsPtr = paramsBytes)
            {
                PaddleNative.PD_ConfigSetModel(_ptr, (IntPtr)programPtr, (IntPtr)paramsPtr);
            }

            predictor = new PaddlePredictor(PaddleNative.PD_PredictorCreate(_ptr));
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (img == "")
            {
                return;
            }

            Mat src = Cv2.ImRead(img);

            Mat resized = MatResize(src, MaxSize);
            Mat padded = MatPadding32(resized);
            Mat normalized = Normalize(padded);
            OpenCvSharp.Size resizedSize = resized.Size();
            using (PaddleTensor input = predictor.GetInputTensor(predictor.InputNames[0]))
            {
                input.Shape = new[] { 1, 3, normalized.Rows, normalized.Cols };
                float[] setData = ExtractMat(normalized);
                input.SetData(setData);
            }

            if (!predictor.Run())
            {
                throw new Exception("PaddlePredictor(Detector) run failed.");
            }

            using (PaddleTensor output = predictor.GetOutputTensor(predictor.OutputNames[0]))
            {
                float[] data = output.GetData<float>();
                int[] shape = output.Shape;

                Mat pred = new Mat(shape[2], shape[3], MatType.CV_32FC1, data);
                Mat cbuf = new Mat();

                Mat roi = pred[0, resizedSize.Height, 0, resizedSize.Width];
                roi.ConvertTo(cbuf, MatType.CV_8UC1, 255);

                Mat dilated = new Mat();
                Mat binary = BoxThreshold != null ?
                   cbuf.Threshold((int)(BoxThreshold * 255), 255, ThresholdTypes.Binary) :
                   cbuf;

                if (DilatedSize != null)
                {
                    Mat ones = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(DilatedSize.Value, DilatedSize.Value));
                    Cv2.Dilate(binary, dilated, ones);
                    ones.Dispose();
                }
                else
                {
                    Cv2.CopyTo(binary, dilated);
                }

                OpenCvSharp.Point[][] contours = dilated.FindContoursAsArray(RetrievalModes.List, ContourApproximationModes.ApproxSimple);

                OpenCvSharp.Size size = src.Size();
                double scaleRate = 1.0 * src.Width / resizedSize.Width;

                RotatedRect[] rects = contours
                    .Where(x => BoxScoreThreahold == null || GetScore(x, pred) > BoxScoreThreahold)
                    .Select(x => Cv2.MinAreaRect(x))
                    .Where(x => x.Size.Width > MinSize && x.Size.Height > MinSize)
                    .Select(rect =>
                    {
                        float minEdge = Math.Min(rect.Size.Width, rect.Size.Height);
                        Size2f newSize = new Size2f(
                            (rect.Size.Width + UnclipRatio * minEdge) * scaleRate,
                            (rect.Size.Height + UnclipRatio * minEdge) * scaleRate);
                        RotatedRect largerRect = new RotatedRect(rect.Center * scaleRate, newSize, rect.Angle);
                        return largerRect;
                    })
                    .OrderBy(v => v.Center.Y)
                    .ThenBy(v => v.Center.X)
                    .ToArray();

                src.Dispose();
                binary.Dispose();
                roi.Dispose();
                cbuf.Dispose();
                pred.Dispose();
                dilated.Dispose();

                //绘图
                Mat src2 = Cv2.ImRead(img);
                for (int i = 0; i < rects.Length; i++)
                {
                    Scalar scalar = Scalar.RandomColor();
                    List<OpenCvSharp.Point> temp = new List<OpenCvSharp.Point>();
                    foreach (var item2 in rects[i].Points())
                    {
                        temp.Add(new OpenCvSharp.Point(item2.X, item2.Y));
                    }
                    List<List<OpenCvSharp.Point>> lltemp = new List<List<OpenCvSharp.Point>>();
                    lltemp.Add(temp);
                    Cv2.Polylines(src2, lltemp, true, scalar);
                }

                if (pictureBox1.Image!=null)
                {
                    pictureBox1.Image.Dispose();
                }

                pictureBox1.Image = BitmapConverter.ToBitmap(src2);
                src2.Dispose();

            }
        }

        private float GetScore(OpenCvSharp.Point[] contour, Mat pred)
        {
            int width = pred.Width;
            int height = pred.Height;
            int[] boxX = contour.Select(v => v.X).ToArray();
            int[] boxY = contour.Select(v => v.Y).ToArray();

            int xmin = Clamp(boxX.Min(), 0, width - 1);
            int xmax = Clamp(boxX.Max(), 0, width - 1);
            int ymin = Clamp(boxY.Min(), 0, height - 1);
            int ymax = Clamp(boxY.Max(), 0, height - 1);

            OpenCvSharp.Point[] rootPoints = contour
                .Select(v => new OpenCvSharp.Point(v.X - xmin, v.Y - ymin))
                .ToArray();
            Mat mask = new Mat(ymax - ymin + 1, xmax - xmin + 1, MatType.CV_8UC1, Scalar.Black);
            mask.FillPoly(new[] { rootPoints }, new Scalar(1));

            Mat croppedMat = pred[ymin, ymax + 1, xmin, xmax + 1];
            float score = (float)croppedMat.Mean(mask).Val0;
            return score;
        }

        public int Clamp(int val, int min, int max)
        {
            if (val < min)
            {
                return min;
            }
            else if (val > max)
            {
                return max;
            }
            return val;
        }

        float[] ExtractMat(Mat src)
        {
            int rows = src.Rows;
            int cols = src.Cols;
            float[] array = new float[rows * cols * 3];
            GCHandle gCHandle = default(GCHandle);
            try
            {
                gCHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
                IntPtr intPtr = gCHandle.AddrOfPinnedObject();
                for (int i = 0; i < src.Channels(); i++)
                {
                    Mat dest = new Mat(rows, cols, MatType.CV_32FC1, intPtr + i * rows * cols * 4, 0L);
                    Cv2.ExtractChannel(src, dest, i);
                    dest.Dispose();
                }
                return array;
            }
            finally
            {
                gCHandle.Free();
            }
        }

        private Mat MatResize(Mat src, int? maxSize)
        {
            if (maxSize == null) return src.Clone();

            OpenCvSharp.Size size = src.Size();
            int longEdge = Math.Max(size.Width, size.Height);
            double scaleRate = 1.0 * maxSize.Value / longEdge;

            return scaleRate < 1.0 ?
                src.Resize(OpenCvSharp.Size.Zero, scaleRate, scaleRate) :
                src.Clone();
        }

        private Mat MatPadding32(Mat src)
        {
            OpenCvSharp.Size size = src.Size();
            OpenCvSharp.Size newSize = new OpenCvSharp.Size(
                32 * Math.Ceiling(1.0 * size.Width / 32),
                32 * Math.Ceiling(1.0 * size.Height / 32));

            return src.CopyMakeBorder(0, newSize.Height - size.Height, 0, newSize.Width - size.Width, BorderTypes.Constant, Scalar.Black);
        }

        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;
        }

    }
}

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

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

相关文章

【完整代码】电商购物系统Python,基于Flask框架实现

一、介绍 电商购物系统Python&#xff0c;基于Flask框架实现。 实现用户查看商品、购买商品、添加购物车、商城订单、编辑个人信息、点击喜欢不喜欢等、商品评论、登录注册、查看物流信息等功能。 实现商家发布商品、查看销售列表、管理商品、物流信息更新、个人信息修改等功能…

腾讯游戏服务器外包二面

1.基础问题 2.网络协议 3.数据结构 3.1二叉树的前序遍历 3.2实现二叉树的前序遍历 https://www.nowcoder.com/practice/5e2135f4d2b14eb8a5b06fab4c938635?tpId295&tqId2291302&ru/exam/oj&qru/ta/format-top101/question-ranking&sourceUrl%2Fexam%2Foj…

如何查找电脑蓝屏原因之详解

一、电脑蓝屏存储位置 电脑蓝屏日志是一种非常常见的错误提示&#xff0c;它经常发生在Windows操作系统中。当Windows系统遇到无法处理的错误时&#xff0c;会自动将错误信息记录在蓝屏日志文件中。这些日志文件通常存储在C盘的目录下windows文件中的Minidump文件夹中。 以dmp格…

Openlayers实战:绘制矩形,正方形,正六边形

Openlayers地图中,绘制图形是非常重要的一个功能。Openlayers主要使用draw类来绘制图形,在实际项目中有时候会绘制矩形和正多边形。 下面的示例是绘制矩形,正方形,正多边形。 效果图 源代码 /* * @Author: 大剑师兰特(xiaozhuanlan),还是大剑师兰特(CSDN) * @此源代…

基于Python爬虫+KNN数字验证码识别系统——机器学习算法应用(含全部工程源码)+训练数据集

目录 前言总体设计系统整体结构图系统流程图 运行环境Python 环境 模块实现1. 数据爬取2. 去噪与分割3. 模型训练及保存4. 准确率验证 系统测试工程源代码下载其它资料下载 前言 本项目利用Python爬虫技术&#xff0c;通过网络爬取验证码图片&#xff0c;并通过一系列的处理步…

QT5项目程序打包成可执行exe程序(绿色版)

一、QT在release模式下编译生成.exe 二、然后新建一个空白文件夹package&#xff0c;再将在release模式下生成的.exe文件复制到新建的文件夹中package。 三、打开QT5的命令行&#xff08;选择项目所使用的的环境&#xff09; 查找项目使用环境 打开命令行 四、在命令行输入命令…

马斯克:未来会涌现大量机器人,与人类比例有望超过1比1

在世界人工智能大会上&#xff0c;特斯拉的马斯克通过网络发表了视频演讲&#xff0c;涵盖了特斯拉人形机器人Optimus、自动驾驶和人工智能等话题。他赞扬了中国的AI产业&#xff0c;并表示中国在决心和实施方面非常出色&#xff0c;包括AI产业发展在内。 特斯拉的人型机器人目…

数学美学:探索“既不是最小值也不是最大值”的魅力

本篇博客会讲解力扣“2733. 既不是最小值也不是最大值”的解题思路&#xff0c;这是题目链接。 本题的思路是&#xff1a; 若数组只有2个元素&#xff0c;显然任意一个元素不是最小值就是最大值。若数组有3个以上的元素&#xff0c;由于提示中的第3点&#xff1a;数组中的所有…

中国首家外资独资期货公司,摩根大通期货持仓龙虎榜的持仓动向和盈亏状况

摩根大通期货&#xff0c;为什么持仓量长期排在期货龙虎榜前列 摩根大通是一家全球领先的金融服务机构&#xff0c;拥有超过200年的历史&#xff0c;业务遍及全球100多个国家和地区。这个期货公司比较神秘&#xff0c;只有上海一个营业部&#xff0c;在业务方向上以机构客户为服…

YOLOv5、YOLOv8改进教程:7. 添加SK-Net注意力机制

论文地址:Selective Kernel NetworksGithub:https://github.com/implus/SKNet如果你是深度学习小白,阅读本文前建议先学习一下 📖《新手入门深度学习》如果你有一定基础,但是缺乏实战经验,可通过 📖《深度学习100例》 补齐基础另外,我们正在通过 🔥365天深度学习训…

ATM模拟-管理员登录用户查询

项目来源&#xff1a;新星计划2023【JavaWeb实现ATM机存取款项目实战】 学习方向报名入口-CSDN社区 目录 管理员登录 管理员登录逻辑 管理员登录主程序 功能实现 代码如下&#xff1a; 用户信息封装 实现功能 代码实现&#xff1a; 业务层代码具体实现 功能实现 业…

linux查看内存总结

参考博客&#xff1a; https://www.atlantic.net/vps-hosting/find-top-10-running-processes-by-memory-and-cpu-usage/ 最简单的命令 free -g 查看还有多少可用的内存 但是有的时候这个提供的信息实在是太少了&#xff0c;例如我今天发现服务器上可用的内存只有50G, 我想知…

第2章 SSD主控和全闪存阵列

通过第一章可知&#xff0c;SSD主要由两大模块组成&#xff1a;主控和闪存介质。其中&#xff0c;主控的作用包括&#xff1a; &#xff08;1&#xff09;实现标准主机接口与主机通信&#xff1b; &#xff08;2&#xff09;实现与闪存的通信&#xff1b; &#xff08;1&#x…

算法与数据结构-队列

文章目录 什么是队列队列和栈的区别 队列的类型顺序队列链式队列循环队列阻塞队列并发队列 总结 什么是队列 队列跟栈一样&#xff0c;也是一种操作受限的线性表数据结构。不过&#xff0c;队列是先进者先出。 队列和栈的区别 栈只支持两个基本操作&#xff1a;入栈 push()和出…

【Kafka】Kafka consumer lag 为负数

前言 最近对Kafka 集群部署了 Kafka_exporter 监控&#xff0c;并集成了 granfana 图标展示。 发现 Consumer Group Lag 有时候为负数。 于是进行一番查询&#xff0c;并总结整理下。 具体情形 从下图可以看出&#xff0c;consumer group 值有时候出现负数的情况。 具体原…

Python 使用 pyc 解决明文密钥问题

文章目录 前言1. pyc 介绍2. py 代码编译2.1 使用命令行编译2.2 使用代码编译 3. 避免名为密钥案例3.1 创建密钥存储代码文件3.2 编译密钥代码3.3 调用密钥代码 前言 写代码过程中&#xff0c;可能遇到一些敏感信息不想明文暴露在代码中的情况&#xff0c;本篇文章介绍使用 py…

多tab之间的sessionStorage能不能直接共享访问?

首先&#xff0c;先理解下一个页面的sessionStorage是怎么回事。 1、当前A页面有sessionStorage值为123&#xff0c;我F5强刷页面&#xff0c;sessionStorage值还在不在&#xff1f; 答&#xff1a;在。 2、当前A页面有sessionStorage值为123&#xff0c;我复制A页面地址在浏览…

浏览器console发送get或post请求

浏览器console发送get或post请求 get请求 var url "http://******:8080/base/testapi/testcurl?urlhttps%3A%2F%2Fwww.baidu.com%2F"; var xhr new XMLHttpRequest(); xhr.open("GET", url, true); xhr.setRequestHeader("Content-Type", &…

RPG++——游戏编辑器的开发

完整资料进入【数字空间】查看——baidu搜索"writebug" 随着当下电子设备的普及以及人们对娱乐需求的上升&#xff0c;电子游戏逐渐走进千家万户。RPG&#xff08;角色扮演&#xff09;游戏作为最经典的游戏种类之一&#xff0c;因其游戏形式多样&#xff0c;自由度…

矢量数据库对比和选择指南

矢量数据库是为实现高维矢量数据的高效存储、检索和相似性搜索而设计的。使用一种称为嵌入的过程&#xff0c;将向量数据表示为一个连续的、有意义的高维向量。 本文将研究存储/检索向量数据和执行相似性搜索的实用方法&#xff0c;在我们深入研究之前&#xff0c;首先先介绍矢…