C# OpenCvSharp DNN 实现百度网盘AI大赛-表格检测第2名方案第一部分-表格边界框检测

目录

说明

效果

模型

项目

代码

frmMain.cs

YoloDet.cs 

参考

下载

其他


说明

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

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

本文使用C# OpenCvSharp DNN 实现百度网盘AI大赛-表格检测第2名方案第一部分-表格边界框检测。

效果

模型

Model Properties
-------------------------
date:2024-10-28T13:52:42.181333
description:Ultralytics YOLO11l model trained on coco.yaml
author:Ultralytics
version:8.3.23
task:detect
license:AGPL-3.0 License (https://ultralytics.com/license)
docs:https://docs.ultralytics.com
stride:32
batch:1
imgsz:[928, 928]
names:{0: 'table'}
---------------------------------------------------------------

Inputs
-------------------------
name:images
tensor:Float[1, 3, 928, 928]
---------------------------------------------------------------

Outputs
-------------------------
name:output0
tensor:Float[1, 5, 17661]
---------------------------------------------------------------

项目

代码

frmMain.cs

using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

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

        YoloDet obj_detector;

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

        DateTime dt1 = DateTime.Now;
        DateTime dt2 = DateTime.Now;

        Mat image;

        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 obj_model_path = "model/yolo_obj_det.onnx";

            obj_detector = new YoloDet(obj_model_path);

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

        }

        private unsafe void button2_Click(object sender, EventArgs e)
        {
            if (image_path == "")
            {
                return;
            }
            textBox1.Text = "检测中,请稍等……";
            pictureBox2.Image = null;
            Application.DoEvents();

            Mat src = new Mat(image_path);

            dt1 = DateTime.Now;
            List<Bbox> result = obj_detector.infer(src);
            dt2 = DateTime.Now;

            //绘制
            Mat draw_img = src.Clone();
            for (int i = 0; i < result.Count; i++)
            {
                Rect r = Rect.FromLTRB(result[i].xmin, result[i].ymin, result[i].xmax, result[i].ymax);

                Cv2.PutText(draw_img, $"table:{result[0].score:P0}", new OpenCvSharp.Point(r.TopLeft.X, r.TopLeft.Y - 10), HersheyFonts.HersheySimplex, 8, Scalar.Red, 8);
                Cv2.Rectangle(draw_img, r, Scalar.Red, thickness: 8);

                //裁剪,保存,为下一步检测做准备
                Mat crop_img = new Mat(src, r);
                Cv2.ImWrite(i + ".jpg", crop_img);
            }
            pictureBox2.Image = new Bitmap(draw_img.ToMemoryStream());
            textBox1.Text = "推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms";
        }
       
        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 System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;namespace OpenCvSharp_DNN_Demo
{public partial class frmMain : Form{public frmMain(){InitializeComponent();}YoloDet obj_detector;string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";string image_path = "";DateTime dt1 = DateTime.Now;DateTime dt2 = DateTime.Now;Mat image;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 obj_model_path = "model/yolo_obj_det.onnx";obj_detector = new YoloDet(obj_model_path);image_path = "test_img/real5.jpg";pictureBox1.Image = new Bitmap(image_path);}private unsafe void button2_Click(object sender, EventArgs e){if (image_path == ""){return;}textBox1.Text = "检测中,请稍等……";pictureBox2.Image = null;Application.DoEvents();Mat src = new Mat(image_path);dt1 = DateTime.Now;List<Bbox> result = obj_detector.infer(src);dt2 = DateTime.Now;//绘制Mat draw_img = src.Clone();for (int i = 0; i < result.Count; i++){Rect r = Rect.FromLTRB(result[i].xmin, result[i].ymin, result[i].xmax, result[i].ymax);Cv2.PutText(draw_img, $"table:{result[0].score:P0}", new OpenCvSharp.Point(r.TopLeft.X, r.TopLeft.Y - 10), HersheyFonts.HersheySimplex, 8, Scalar.Red, 8);Cv2.Rectangle(draw_img, r, Scalar.Red, thickness: 8);//裁剪,保存,为下一步检测做准备Mat crop_img = new Mat(src, r);Cv2.ImWrite(i + ".jpg", crop_img);}pictureBox2.Image = new Bitmap(draw_img.ToMemoryStream());textBox1.Text = "推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms";}private void pictureBox2_DoubleClick(object sender, EventArgs e){Common.ShowNormalImg(pictureBox2.Image);}private void pictureBox1_DoubleClick(object sender, EventArgs e){Common.ShowNormalImg(pictureBox1.Image);}}
}

YoloDet.cs 

using OpenCvSharp;
using OpenCvSharp.Dnn;
using System;
using System.Collections.Generic;
using System.Linq;namespace OpenCvSharp_DNN_Demo
{internal class YoloDet{Net model;int[] resize_shape = new int[2] { 928, 928 };public YoloDet(string model_path){model = CvDnn.ReadNetFromOnnx(model_path);}unsafe public List<Bbox> infer(Mat srcimg, float score = 0.4f){int ori_h = srcimg.Rows;int ori_w = srcimg.Cols;img_preprocessMat img;int new_w = 0;int new_h = 0;int left = 0;int top = 0;img = Common.ResizePad(srcimg, resize_shape[0], ref new_w, ref new_h, ref left, ref top);//Cv2.ImWrite("0.jpg", img);img.ConvertTo(img, MatType.CV_32FC3, 1.0 / 255.0);Mat blob = CvDnn.BlobFromImage(img);model.SetInput(blob);//模型推理,读取推理结果Mat[] outs = new Mat[1] { new Mat() };string[] outBlobNames = model.GetUnconnectedOutLayersNames().ToArray();model.Forward(outs, outBlobNames);img_postprocessfloat x_factor = (float)ori_w / new_w;float y_factor = (float)ori_h / new_h;List<Rect> boxes = new List<Rect>();List<float> scores = new List<float>();int rows = outs[0].Size(2);//将推理结果转为float数据类型//5, 17661Mat result_mat = new Mat(5, 17661, MatType.CV_32F, outs[0].Data);result_mat = result_mat.T();//string str = result_mat.Dump();for (int i = 0; i < rows; i++){float* ptr = (float*)(result_mat.Ptr(i).ToPointer());float max_score = ptr[4];//float max_score = result_mat.At<float>(i, 4);if (max_score >= score){//At效率不高//float x1 = result_mat.At<float>(i, 0);//float y2 = result_mat.At<float>(i, 1);//float w2 = result_mat.At<float>(i, 2);//float h2 = result_mat.At<float>(i, 3);float x = ptr[0];float y = ptr[1];float w = ptr[2];float h = ptr[3];int xmin = Math.Max((int)((x - w / 2 - left) * x_factor), 0);int ymin = Math.Max((int)((y - h / 2 - top) * y_factor), 0);boxes.Add(new Rect(xmin, ymin, (int)(w * x_factor), (int)(h * y_factor)));scores.Add(max_score);}}int[] indices;CvDnn.NMSBoxes(boxes, scores, score, 0.4f, out indices);int num_keep = indices.Length;List<Bbox> bboxes = new List<Bbox>();for (int i = 0; i < num_keep; i++){int ind = indices[i];bboxes.Add(new Bbox(boxes[ind].X, boxes[ind].Y, Math.Min(boxes[ind].X + boxes[ind].Width, ori_w - 1), Math.Min(boxes[ind].Y + boxes[ind].Height, ori_h - 1), scores[ind]));}return bboxes;}}
}/*Model Properties
-------------------------
date:2024-10-28T13:52:42.181333
description:Ultralytics YOLO11l model trained on coco.yaml
author:Ultralytics
version:8.3.23
task:detect
license:AGPL-3.0 License (https://ultralytics.com/license)
docs:https://docs.ultralytics.com
stride:32
batch:1
imgsz:[928, 928]
names:{0: 'table'}
---------------------------------------------------------------Inputs
-------------------------
name:images
tensor:Float[1, 3, 928, 928]
---------------------------------------------------------------Outputs
-------------------------
name:output0
tensor:Float[1, 5, 17661]
---------------------------------------------------------------*/

参考

https://github.com/hpc203/TableDetectionhttps://aistudio.baidu.com/projectdetail/5398861?searchKeyword=%E8%A1%A8%E6%A0%BC%E6%A3%80%E6%B5%8B%E5%A4%A7%E8%B5%9B&searchTab=ALL

下载

源码下载

其他

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

C# OpenCvSharp DNN 第三部分-表格方向识别-CSDN博客

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

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

相关文章

图形学笔记 - 5. 光线追踪 - RayTracing

Whitted-Style Ray tracing 为什么要光线追踪 光栅化不能很好地处理全局效果 软阴影尤其是当光线反射不止一次的时候 栅格化速度很快&#xff0c;但质量相对较低 光线追踪是准确的&#xff0c;但速度很慢 光栅化&#xff1a;实时&#xff0c;光线追踪&#xff1a;离线~10K …

day15 python(3)——python基础(完结!!)

【没有所谓的运气&#x1f36c;&#xff0c;只有绝对的努力✊】 目录 1、函数 1.1 函数传参中的拆包 1.2 匿名函数的定义 1.3 匿名函数练习 1.4 匿名函数应用——列表中的字典排序 2、面向对象 OOP 2.1 面向对象介绍 2.2 类和对象 2.3 类的构成和设计 2.4 面向对象代码…

C语言破解鸡蛋问题

破解鸡蛋问题 问题分析算法思路选择枚举法思路数据结构应用数组的应用变量的合理定义代码实现伪代码示例C 语言代码展示结果验证与分析不同输入验证复杂度分析问题分析 在这个 “鸡蛋问题” 中,已知条件表明这堆鸡蛋按两个两个地拿、三个三个地拿、四个四个地拿时,最后都剩一…

XXE-Lab靶场漏洞复现

1.尝试登录 输入账号admin/密码admin进行登录&#xff0c;并未有页面进行跳转 2.尝试抓包分析请求包数据 我们可以发现页面中存在xml请求&#xff0c;我们就可以构造我们的xml请求语句来获取想要的数据 3.构造语句 <?xml version"1.0" ?> <!DOCTYPE fo…

安卓主板_MTK联发科android主板方案

在当前智能设备的发展中&#xff0c;安卓主板的配置灵活性和性能优化显得尤为重要。安卓主板的联发科方案&#xff0c;在芯片上&#xff0c;搭载联发科MTK6761、MT8766、MT6765、MT6762、MT8768、MT8390、MTK8370以及MT8788等型号&#xff0c;均基于64位的四核或八核架构设计。…

计算机网络知识点全梳理(三.TCP知识点总结)

目录 TCP基本概念 为什么需要TCP 什么是TCP 什么是TCP链接 如何唯一确定一个 TCP 连接 TCP三次握手 握手流程 为什么是三次握手&#xff0c;而不是两次、四次 为什么客户端和服务端的初始序列号 ISN 不同 既然 IP 层会分片&#xff0c;为什么 TCP 层还需要 MSS TCP四…

0004.基于springboot+elementui的在线考试系统

适合初学同学练手项目&#xff0c;部署简单&#xff0c;代码简洁清晰&#xff1b; 愿世界和平再无bug 一、系统架构 前端&#xff1a;vue| elementui 后端&#xff1a;springboot | mybatis-plus 环境&#xff1a;jdk1.8 | mysql | maven 二、登录角色 1.管理员 2.老师 …

[面试题]--索引用了什么数据结构?有什么特点?

答&#xff1a;使用了B树&#xff1a; 时间复杂度&#xff1a;O(logN),可以有效控制树高 B树特点&#xff1a; 1.叶子节点之间有相互链接的作用&#xff0c;会指向下一个相近的兄弟节点。 MySQL在组织叶子节点使用的是双向链表 2.非叶子节点的值都保存在叶子节点当中 MySQL非叶…

ansible剧本快速上手

playbook剧本介绍 是什么&#xff1a;能户长期保存&#xff0c;且能实现批量配置、部署…的文件格式&#xff1a;yaml格式。用 空格 冒号 头号 句号语法检测&#xff1a;ansible-playbook --syntax-check install-zabbix.yaml或则 -C检测取消默认任务&#xff1a;gather_facts…

Element plus 下拉框组件选中一个选项后显示的是 value 而不是 label

最近刚进行 Vue3 Element plus 项目实践&#xff0c;在进行表单二次封装的时候&#xff0c;表单元素 select 下拉框组件选中一个选项后显示的是 value 而不是 label&#xff0c;下面上代码&#xff1a; 原来的写法&#xff1a; <el-selectv-if"v.type select"…

重新定义页签!Choerodon UI Tabs让管理更高效

01 引言 Tabs 组件通过提供平级区域&#xff0c;将大块内容进行有效的收纳和展现&#xff0c;从而保持界面整洁。但在企业应用的快速发展中&#xff0c;这样传统的页签组件已无法满足我们对界面布局和个性化展示的追求。Choerodon UI Tabs 组件通过支持多级分组、个性化配置、…

Eureka学习笔记-服务端

Eureka学习笔记 服务端 模块设计 Resources &#xff1a;这部分对外暴露了一系列的 Restful 接口。Eureka Client 的注册、心跳、获取服务列表等操作都需要调用这些接口。另外&#xff0c;其他的 Server 在同步 Registry 时也需要调用这些接口。Controller &#xff1a;这里提…

Java创建对象有几种方式?

大家好&#xff0c;我是锋哥。今天分享关于【Java创建对象有几种方式?】面试题。希望对大家有帮助&#xff1b; Java创建对象有几种方式? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Java 中&#xff0c;创建对象的方式主要有几种。以下是常见的几种对象创…

C++特殊类设计(单例模式等)

目录 引言 1.请设计一个类&#xff0c;不能被拷贝 2. 请设计一个类&#xff0c;只能在堆上创建对象 为什么设置实例的方法为静态成员呢 3. 请设计一个类&#xff0c;只能在栈上创建对象 4. 请设计一个类&#xff0c;不能被继承 5. 请设计一个类&#xff0c;只能创建一个对…

[LeetCode-Python版]21. 合并两个有序链表(迭代+递归两种解法)

题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] 示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输出&#x…

【C++】- 掌握STL List类:带你探索双向链表的魅力

文章目录 前言&#xff1a;一.list的介绍及使用1. list的介绍2. list的使用2.1 list的构造2.2 list iterator的使用2.3 list capacity2.4 list element access2.5 list modifiers2.6 list的迭代器失效 二.list的模拟实现1. list的节点2. list的成员变量3.list迭代器相关问题3.1…

Facebook的隐私保护政策:用户数据如何在平台上被管理?

在当今数字化世界&#xff0c;社交平台如何管理用户数据并保护隐私成为了一个热点话题。作为全球最大的社交网络&#xff0c;Facebook&#xff08;现Meta&#xff09;在数据隐私方面的政策备受关注。本文将简要介绍Facebook的隐私保护措施&#xff0c;以及用户数据如何在平台上…

Git-分支(branch)常用命令

分支 我们在做项目开发的时候&#xff0c;无论是软件项目还是其他机械工程项目&#xff0c;我们为了提高效率以及合理的节省时间等等原因&#xff0c;现在都不再是线性进行&#xff0c;而是将一个项目抽离出诸进行线&#xff0c;每一条线在git中我们就叫做分支&#xff0c;bran…

0101多级nginx代理websocket配置-nginx-web服务器

1. 前言 项目一些信息需要通过站内信主动推动给用户&#xff0c;使用websocket。web服务器选用nginx&#xff0c;但是域名是以前通过阿里云申请的&#xff0c;解析ip也是阿里云的服务器&#xff0c;甲方不希望更换域名。新的系统需要部署在内网服务器&#xff0c;简单拓扑图如…

Android Stduio 2024版本设置前进和后退按钮显示在主界面

Android Studio 2024&#xff08;Ladybug&#xff09;安装后发现前进和后退按钮不显示在主界面的工具栏&#xff0c;且以前在View中设置的办法无效&#xff1a; Android Studio 2024&#xff08;Ladybug&#xff09;的设置方式&#xff1a; File->Settings->Appearance&…