C# OpenCvSharp DNN 实现百度网盘AI大赛-表格检测第2名方案第三部分-表格方向识别

目录

说明

效果

模型

项目

​编辑

代码

参考

下载

其他


说明

百度网盘AI大赛-表格检测的第2名方案。

该算法包含表格边界框检测、表格分割和表格方向识别三个部分,首先,ppyoloe-plus-x 对边界框进行预测,并对置信度较高的表格边界框(box)进行裁剪。裁剪后的单个表格实例会送入到DBNet中进行语义分割,分割结果通过opencv轮廓处理获得表格关键点(point)。之后,我们根据DBNet计算的关键点在裁剪后的单个表格实例上绘制表格边界。最后,PP-LCNet结合表格边界先验和表格实例图像,对表格的方向进行预测,并根据之前定义的几何轮廓点与语义轮廓点的对应关系,将几何轮廓点映射为语义轮廓点。

本文使用C# OpenCvSharp DNN 实现百度网盘AI大赛-表格检测第2名方案第三部分-表格方向识别

效果

模型

Model Properties
-------------------------
---------------------------------------------------------------

Inputs
-------------------------
name:input
tensor:Float[-1, 3, 624, 624]
---------------------------------------------------------------

Outputs
-------------------------
name:linear_1.tmp_1
tensor:Float[-1, 4]
---------------------------------------------------------------

项目

代码

using OpenCvSharp;
using OpenCvSharp.Dnn;
using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace OpenCvSharp_DNN_Demo
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string image_path = "";
        string startupPath;
        string classer_path;

        DateTime dt1 = DateTime.Now;
        DateTime dt2 = DateTime.Now;
        string model_path;
        Mat image;

        Mat result_mat;
        Mat result_image;
        Mat result_mat_to_float;

        Net opencv_net;
        Mat BN_image;

        float[] result_array;

        int max_image_length;
        Mat max_image;
        Rect roi;

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

            pictureBox1.Image = null;
            pictureBox2.Image = null;
            textBox1.Text = "";

            image_path = ofd.FileName;
            pictureBox1.Image = new Bitmap(image_path);
            image = new Mat(image_path);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            string model_path = "model/paddle_cls.onnx";
            opencv_net = CvDnn.ReadNetFromOnnx(model_path);

            image_path = "test_img/1.jpg";
            pictureBox1.Image = new Bitmap(image_path);

        }

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

            if (image_path == "")
            {
                return;
            }
            textBox1.Text = "检测中,请稍等……";
            pictureBox2.Image = null;
            Application.DoEvents();

            Mat image = new Mat(image_path);

            //缩放图片
            max_image_length = image.Cols > image.Rows ? image.Cols : image.Rows;
            max_image = Mat.Zeros(new OpenCvSharp.Size(max_image_length, max_image_length), MatType.CV_8UC3);
            roi = new Rect(0, 0, image.Cols, image.Rows);
            image.CopyTo(new Mat(max_image, roi));

            //数据归一化处理
            BN_image = CvDnn.BlobFromImage(max_image, 1 / 255.0, new OpenCvSharp.Size(624, 624), new Scalar(0, 0, 0), true, false);

            //配置图片输入数据
            opencv_net.SetInput(BN_image);

            dt1 = DateTime.Now;
            //模型推理,读取推理结果
            result_mat = opencv_net.Forward();
            dt2 = DateTime.Now;

            //将推理结果转为float数据类型
            result_mat_to_float = new Mat(1, 4, MatType.CV_32F, result_mat.Data);

            //将数据读取到数组中
            result_mat_to_float.GetArray<float>(out result_array);

            float max = result_array.Max(); // 
            int maxIndex = Array.IndexOf(result_array, max); // 获取最大值的索引位置
            //语义左上角位于几何左上角,定义为0;
            //语义左上角位于几何右上角,定义为1;
            //语义左上角位于几何右下角,定义了2;
            //语义左上角位于几何左下角,定义为3。
            
            textBox1.Text = "推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms\r\n";
            string msg = "";
            if (maxIndex == 0) {
                msg = "语义左上角位于几何左上角";
            }
            else if (maxIndex == 1)
            {
                msg = "语义左上角位于几何右上角";
            }
            else if (maxIndex == 2)
            {
                msg = "语义左上角位于几何右下角";
            }
            else if (maxIndex == 3)
            {
                msg = "语义左上角位于几何左下角";
            }
            textBox1.Text += "\r\n" + msg;
        }

        private void pictureBox2_DoubleClick(object sender, EventArgs e)
        {
            Common.ShowNormalImg(pictureBox2.Image);
        }
        
        private void pictureBox1_DoubleClick(object sender, EventArgs e)
        {
            Common.ShowNormalImg(pictureBox1.Image);
        }
    }
}
 

using OpenCvSharp;
using OpenCvSharp.Dnn;
using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;namespace OpenCvSharp_DNN_Demo
{public partial class frmMain : Form{public frmMain(){InitializeComponent();}string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";string image_path = "";string startupPath;string classer_path;DateTime dt1 = DateTime.Now;DateTime dt2 = DateTime.Now;string model_path;Mat image;Mat result_mat;Mat result_image;Mat result_mat_to_float;Net opencv_net;Mat BN_image;float[] result_array;int max_image_length;Mat max_image;Rect roi;private void button1_Click(object sender, EventArgs e){OpenFileDialog ofd = new OpenFileDialog();ofd.Filter = fileFilter;if (ofd.ShowDialog() != DialogResult.OK) return;pictureBox1.Image = null;pictureBox2.Image = null;textBox1.Text = "";image_path = ofd.FileName;pictureBox1.Image = new Bitmap(image_path);image = new Mat(image_path);}private void Form1_Load(object sender, EventArgs e){string model_path = "model/paddle_cls.onnx";opencv_net = CvDnn.ReadNetFromOnnx(model_path);image_path = "test_img/1.jpg";pictureBox1.Image = new Bitmap(image_path);}private unsafe void button2_Click(object sender, EventArgs e){if (image_path == ""){return;}if (image_path == ""){return;}textBox1.Text = "检测中,请稍等……";pictureBox2.Image = null;Application.DoEvents();Mat image = new Mat(image_path);//缩放图片max_image_length = image.Cols > image.Rows ? image.Cols : image.Rows;max_image = Mat.Zeros(new OpenCvSharp.Size(max_image_length, max_image_length), MatType.CV_8UC3);roi = new Rect(0, 0, image.Cols, image.Rows);image.CopyTo(new Mat(max_image, roi));//数据归一化处理BN_image = CvDnn.BlobFromImage(max_image, 1 / 255.0, new OpenCvSharp.Size(624, 624), new Scalar(0, 0, 0), true, false);//配置图片输入数据opencv_net.SetInput(BN_image);dt1 = DateTime.Now;//模型推理,读取推理结果result_mat = opencv_net.Forward();dt2 = DateTime.Now;//将推理结果转为float数据类型result_mat_to_float = new Mat(1, 4, MatType.CV_32F, result_mat.Data);//将数据读取到数组中result_mat_to_float.GetArray<float>(out result_array);float max = result_array.Max(); // int maxIndex = Array.IndexOf(result_array, max); // 获取最大值的索引位置//语义左上角位于几何左上角,定义为0;//语义左上角位于几何右上角,定义为1;//语义左上角位于几何右下角,定义了2;//语义左上角位于几何左下角,定义为3。textBox1.Text = "推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms\r\n";string msg = "";if (maxIndex == 0) {msg = "语义左上角位于几何左上角";}else if (maxIndex == 1){msg = "语义左上角位于几何右上角";}else if (maxIndex == 2){msg = "语义左上角位于几何右下角";}else if (maxIndex == 3){msg = "语义左上角位于几何左下角";}textBox1.Text += "\r\n" + msg;}private void pictureBox2_DoubleClick(object sender, EventArgs e){Common.ShowNormalImg(pictureBox2.Image);}private void pictureBox1_DoubleClick(object sender, EventArgs e){Common.ShowNormalImg(pictureBox1.Image);}}
}

参考

https://github.com/hpc203/TableDetection

下载

源码下载

其他

C# OpenCvSharp DNN 第一部分-表格边界框检测-CSDN博客

C# OnnxRuntime 第二部分-表格分割-CSDN博客

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

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

相关文章

go语言结构体实现数据结构队列(先进先出)存储数据(逐行注释)

正在学习go语言中&#xff0c;欢迎提出宝贵意见 import ("fmt""sync" )// 数据队列以链表的形式存储数据&#xff0c;每个节点存储一个任意类型的数据&#xff0c; // 创建数据队列、添加数据、删除数据、获取队列长度&#xff0c;每个数据存储在一个节点…

Excel + Notepad + CMD 命令行批量修改文件名

注意&#xff1a;该方式为直接修改原文件的文件名&#xff0c;不会生成新文件 新建Excel文件 A列&#xff1a;固定为 renB列&#xff1a;原文件名称C列&#xff1a;修改后保存的名称B列、C列&#xff0c;需要带文件后缀&#xff0c;为txt文件就是.txt结尾&#xff0c;为png图片…

数据结构-排序(来自于王道)

排序的基本概念 插入排序 在这个算法中&#xff0c;除了输入的数组本身&#xff0c;没有使用额外的数据结构来存储数据&#xff0c;所有的操作都是在原数组上进行的。因此&#xff0c;无论输入数组的大小 n 是多少&#xff0c;算法执行过程中所占用的额外空间是固定的&#xff…

MySQL中DELETE、DROP和TRUNCATE的区别是什么?

MySQL中&#xff0c;DELETE、DROP和TRUNCATE是用于数据管理的三个重要命令&#xff0c;但它们之间存在显著的区别。以下是它们的主要差异&#xff1a; 一、用法不同 DROP 用途&#xff1a;用于删除整个表及其结构。语法&#xff1a;DROP TABLE 表名;特点&#xff1a;在执行DRO…

算力介绍与解析

算力&#xff08;Computing Power&#xff09;是指计算机系统在单位时间内处理数据和执行计算任务的能力。算力是衡量计算机性能的重要指标&#xff0c;直接影响计算任务的速度和效率。 算力的分类和单位 a. 基础算力&#xff1a;以CPU的计算能力为主。适用于各个领域的计算。…

SVN(Subversion)教程

SVN&#xff08;Subversion&#xff09;教程&#xff1a;版本控制入门 什么是 SVN&#xff1f; SVN&#xff08;Subversion&#xff09;是一个集中式版本控制系统&#xff0c;用于管理代码、文档等文件的版本历史。它帮助团队协作开发&#xff0c;提供版本跟踪、文件还原和冲…

vite搭建前端工程

vite简介 vite预构建 将非 ESM 规范的代码转换为符合 ESM 规范的代码,另外就是将第三方依赖内部的多个文件合并为一个,减少 http 请求数量 简单来说,vite在一开始将应用中的模块区分为依赖和源码两类 「依赖部分」更多指的是代码中使用到的第三方模块,比如 vue、lodash、r…

【编译器】传统编译器和AI/ML编译器总结

前言 本文总结了传统编译器和AI/ML编译器&#xff0c;可作为学习、研究、研发的参考资料。 1.编译器-GC Clang Clang是一个C、C、Objective-C和Objective-C编程语言的编译器前端。它采用了LLVM作为其后端&#xff0c;由LLVM2.6开始&#xff0c;一起发布新版本。它的目标是提供一…

使用阿里云Certbot-DNS-Aliyun插件自动获取并更新免费SSL泛域名(通配符)证书

进入nginx docker&#xff0c;一般是Alpine Linux系统 1. 依次执行命令: sudo docker-compose exec nginx bashapk updateapk add certbot apk add --no-cache python3 python3-dev build-baseapk add python3 py3-pippip3 install --upgrade pippip3 install certbot-dns-ali…

IMUX6LL嵌入式-Linux开发中的头文件汇总介绍

sys/mman.h 详见 https://blog.csdn.net/wenhao_ir/article/details/144487608 sys/types.h 详见 https://blog.csdn.net/wenhao_ir/article/details/144487608 sys/stat.h 详见 https://blog.csdn.net/wenhao_ir/article/details/144487608 unistd.h 详见 https://blog…

spring boot框架优劣势分析

优势&#xff08;Advantages&#xff09;: 1. 快速开发&#xff08;Rapid Development&#xff09;&#xff1a; • Spring Boot通过提供大量的默认配置和自动配置功能&#xff0c;极大地减少了开发过程中的配置工作量&#xff0c;从而加快了开发速度。 2. 简化部署&#xff08…

【设计模式】如何用C++实现观察者模式【发布订阅机制】

【设计模式】如何用C实现观察者模式【发布订阅机制】 一、问题背景 代码质量影响生活质量。最近工作中频繁接触各种设计模式&#xff0c;深刻体会到优秀的设计模式不仅能显著降低后续维护的压力&#xff0c;还能提升开发效率。观察者模式作为一种降低耦合度、提高扩展性的利器…

企业架构划分探讨:业务架构与IT架构的利与弊

在企业架构&#xff08;EA&#xff09;的江湖里&#xff0c;大家一直致力于如何把企业的复杂性简化成有条有理的架构蓝图。有人选择把企业架构分成业务架构和IT架构&#xff0c;而IT架构又进一步细分为应用架构、数据架构和技术架构。但一提到这种划分方式&#xff0c;总有人跳…

QT:在线安装与离线安装

QT 学习系列 QT&#xff1a;在线安装与离线安装 QT 学习系列一、安装&#xff08;一&#xff09;离线安装windows系统Linux 系统Mac 系统 &#xff08;二&#xff09;在线安装 二、 环境变量配置三、验证总结 一、安装 &#xff08;一&#xff09;离线安装 windows系统 获取…

FFmpeg功能使用

步骤&#xff1a;1&#xff0c;安装FFmpeg Download FFmpeg 在这里点击->Windows builds from gyan.dev&#xff1b;如下图 会跳到另外的下载界面&#xff1a; 在里面下拉选择点击ffmpeg-7.1-essentials_build.zip&#xff1a; 即可下载到FFmpeg&#xff1b; 使用&#…

ARM/Linux嵌入式面经(五六):科华数据

经典3分钟自我介绍,然后有两个面试官,第一个面试官偏基础八股, 文章目录 1、c++11和17的主要区别C++11的新特性C++17的新特性及与C++11的区别面试官追问及回答2、stl中使用的比较多的容器3、map的底层实现数据结构问题回答面试官追问及回答4、有没有使用过其他的数据结构5、…

etcd集群常见日志

1、节点失去领导者 {"level":"info","ts":"2024-05-07T01:54:04.948Z","logger":"raft","caller":"etcdserver/zap_raft.go:77","msg":"raft.node: 9afce9447872453 lost le…

【Python网络爬虫笔记】11- Xpath精准定位元素

目录 一、Xpath 在 Python 网络爬虫中的作用&#xff08;一&#xff09;精准定位元素&#xff08;二&#xff09;应对动态网页&#xff08;三&#xff09;数据结构化提取 二、Xpath 的常用方法&#xff08;一&#xff09;节点选取&#xff08;二&#xff09;谓词筛选&#xff0…

Vue 学习-基础

1 声明式渲染 能在改变时触发更新的状态被称作是响应式的。我们可以使用 Vue 的 reactive() API 来声明响应式状态。reactive() 只适用于对象 (包括数组和内置类型&#xff0c;如 Map 和 Set)。而另一个 API ref() 则可以接受任何值类型。ref 会返回一个包裹对象&#xff0c;并…

24. 生成器

一、什么是生成器 利用迭代器&#xff0c;我们可以每次迭代获取数据&#xff08;通过 next() 方法&#xff09;时按照特定的规律进行生成。但是在实现一个迭代器时&#xff0c;关于当前迭代的状态需要我们自己记录&#xff0c;进而才能根据当前状态生成下一个数据。为了达到记录…