C# OpenCvSharp 部署表格检测

目录

说明

效果

模型

项目

代码

下载

参考


C# OpenCvSharp 部署表格检测

说明

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

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

效果

模型

paddle_cls.onnx

Model Properties



Inputs


name:input

tensor:Float[-1, 3, 624, 624]


Outputs


name:linear_1.tmp_1

tensor:Float[-1, 4]


yolo_edge_det.onnx

Model Properties


date:2024-10-28T08:16:43.725877

description:Ultralytics YOLO11l-seg model trained on coco-seg.yaml

author:Ultralytics

version:8.3.23

task:segment

license:AGPL-3.0 License (https://ultralytics.com/license)

docs:https://docs.ultralytics.com

stride:32

batch:1

imgsz:[800, 800]

names:{0: 'table'}


Inputs


name:images

tensor:Float[1, 3, 800, 800]


Outputs


name:output0

tensor:Float[1, 37, 13125]

name:output1

tensor:Float[1, 32, 200, 200]


yolo_obj_det.onnx

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]


项目

代码

using OpenCvSharp;

using System;

using System.Diagnostics;

using System.Drawing;

using System.Drawing.Imaging;

using System.Runtime.InteropServices;

using System.Text;

using System.Windows.Forms;

namespace TableDetection

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

Stopwatch stopwatch = new Stopwatch();

Mat image;

string image_path;

string startupPath;

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

const string DllName = "TableDetectionSharp.dll";

IntPtr engine;

/*

//初始化

extern "C" _declspec(dllexport) int __cdecl init(void** engine, char* obj_model_path, char* edge_model_path, char* cls_model_path, char* msg);

//tableDet

extern "C" _declspec(dllexport) int __cdecl tableDet(void* engine, Mat* image, char* msg, int* out_imgs_size, Mat* out_img1, Mat* out_img2, Mat* out_img3);

//释放

extern "C" _declspec(dllexport) void __cdecl destroy(void* engine);

*/

DllImport(DllName, EntryPoint = "init", CallingConvention = CallingConvention.Cdecl)

internal extern static int init(ref IntPtr engine, string obj_model_path, string edge_model_path, string cls_model_path, StringBuilder msg);

DllImport(DllName, EntryPoint = "tableDet", CallingConvention = CallingConvention.Cdecl)

internal extern static int tableDet(IntPtr engine, IntPtr image, StringBuilder msg, ref int out_imgs_size, IntPtr out_img1, IntPtr out_img2, IntPtr out_img3);

DllImport(DllName, EntryPoint = "destroy", CallingConvention = CallingConvention.Cdecl)

internal extern static int destroy(IntPtr engine);

private void Form1_Load(object sender, EventArgs e)

{

startupPath = Application.StartupPath;

string obj_model_path = startupPath + "\\model\\yolo_obj_det.onnx";

string edge_model_path = startupPath + "\\model\\yolo_edge_det.onnx";

string cls_model_path = startupPath + "\\model\\paddle_cls.onnx";

StringBuilder msg = new StringBuilder(512);

int res = init(ref engine, obj_model_path, edge_model_path, cls_model_path, msg);

if (res == -1)

{

MessageBox.Show(msg.ToString());

return;

}

else

{

Console.WriteLine(msg.ToString());

}

image_path = startupPath + "\\test_img\\real5.jpg";

pictureBox1.Image = new Bitmap(image_path);

image = new Mat(image_path);

}

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

}

Mat out_img1;

Mat out_img2;

Mat out_img3;

private void button2_Click(object sender, EventArgs e)

{

if (image_path == "")

{

return;

}

button2.Enabled = false;

Application.DoEvents();

Cv2.DestroyAllWindows();

if (image != null) image.Dispose();

if (out_img1 != null) out_img1.Dispose();

if (out_img2 != null) out_img2.Dispose();

if (out_img3 != null) out_img3.Dispose();

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

StringBuilder msg = new StringBuilder(512);

int out_imgs_size = 0;

image = new Mat(image_path);

out_img1 = new Mat();

out_img2 = new Mat();

out_img3 = new Mat();

stopwatch.Restart();

int res = tableDet(engine, image.CvPtr, msg, ref out_imgs_size, out_img1.CvPtr, out_img2.CvPtr, out_img3.CvPtr);

if (res == 0)

{

stopwatch.Stop();

double costTime = stopwatch.Elapsed.TotalMilliseconds;

if (out_imgs_size >= 1)

{

pictureBox2.Image = new Bitmap(out_img1.ToMemoryStream());

}

if (out_imgs_size >= 2)

{

Cv2.ImShow("2", out_img2);

}

if (out_imgs_size >= 3)

{

Cv2.ImShow("3", out_img3);

}

textBox1.Text = $"耗时:{costTime:F2}ms";

}

else

{

textBox1.Text = "识别失败";

}

button2.Enabled = true;

}

private void Form1_FormClosed(object sender, FormClosedEventArgs e)

{

destroy(engine);

}

private void button3_Click(object sender, EventArgs e)

{

if (pictureBox2.Image == null)

{

return;

}

Bitmap output = new Bitmap(pictureBox2.Image);

var sdf = new SaveFileDialog();

sdf.Title = "保存";

sdf.Filter = "Images (*.jpg)|*.jpg|Images (*.png)|*.png|Images (*.bmp)|*.bmp";

if (sdf.ShowDialog() == DialogResult.OK)

{

switch (sdf.FilterIndex)

{

case 1:

{

output.Save(sdf.FileName, ImageFormat.Jpeg);

break;

}

case 2:

{

output.Save(sdf.FileName, ImageFormat.Png);

break;

}

case 3:

{

output.Save(sdf.FileName, ImageFormat.Bmp);

break;

}

}

MessageBox.Show("保存成功,位置:" + sdf.FileName);

}

}

}

}

复制代码
using OpenCvSharp;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace TableDetection
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Stopwatch stopwatch = new Stopwatch();
        Mat image;
        string image_path;
        string startupPath;
        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        const string DllName = "TableDetectionSharp.dll";
        IntPtr engine;
        /*
        //初始化
        extern "C" _declspec(dllexport) int __cdecl  init(void** engine, char* obj_model_path, char*  edge_model_path, char* cls_model_path, char* msg);

        //tableDet
        extern "C" _declspec(dllexport) int __cdecl  tableDet(void* engine, Mat* image, char* msg, int* out_imgs_size, Mat* out_img1, Mat* out_img2, Mat* out_img3);

        //释放
        extern "C" _declspec(dllexport) void __cdecl destroy(void* engine);
         */

        [DllImport(DllName, EntryPoint = "init", CallingConvention = CallingConvention.Cdecl)]
        internal extern static int init(ref IntPtr engine, string obj_model_path, string edge_model_path, string cls_model_path, StringBuilder msg);

        [DllImport(DllName, EntryPoint = "tableDet", CallingConvention = CallingConvention.Cdecl)]
        internal extern static int tableDet(IntPtr engine, IntPtr image, StringBuilder msg, ref int out_imgs_size, IntPtr out_img1, IntPtr out_img2, IntPtr out_img3);

        [DllImport(DllName, EntryPoint = "destroy", CallingConvention = CallingConvention.Cdecl)]
        internal extern static int destroy(IntPtr engine);

        private void Form1_Load(object sender, EventArgs e)
        {
            startupPath = Application.StartupPath;

            string obj_model_path = startupPath + "\\model\\yolo_obj_det.onnx";
            string edge_model_path = startupPath + "\\model\\yolo_edge_det.onnx";
            string cls_model_path = startupPath + "\\model\\paddle_cls.onnx";

            StringBuilder msg = new StringBuilder(512);

            int res = init(ref engine, obj_model_path, edge_model_path, cls_model_path, msg);
            if (res == -1)
            {
                MessageBox.Show(msg.ToString());
                return;
            }
            else
            {
                Console.WriteLine(msg.ToString());
            }
            image_path = startupPath + "\\test_img\\real5.jpg";
            pictureBox1.Image = new Bitmap(image_path);
            image = new Mat(image_path);
        }

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

        Mat out_img1;
        Mat out_img2;
        Mat out_img3;

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

            button2.Enabled = false;

            Application.DoEvents();

            Cv2.DestroyAllWindows();
            if (image != null) image.Dispose();
            if (out_img1 != null) out_img1.Dispose();
            if (out_img2 != null) out_img2.Dispose();
            if (out_img3 != null) out_img3.Dispose();
            if (pictureBox1.Image != null) pictureBox1.Image.Dispose();

            StringBuilder msg = new StringBuilder(512);
            int out_imgs_size = 0;
            image = new Mat(image_path);
            out_img1 = new Mat();
            out_img2 = new Mat();
            out_img3 = new Mat();

            stopwatch.Restart();

            int res = tableDet(engine, image.CvPtr, msg, ref out_imgs_size, out_img1.CvPtr, out_img2.CvPtr, out_img3.CvPtr);
            if (res == 0)
            {
                stopwatch.Stop();
                double costTime = stopwatch.Elapsed.TotalMilliseconds;
                if (out_imgs_size >= 1)
                {
                    pictureBox2.Image = new Bitmap(out_img1.ToMemoryStream());
                }

                if (out_imgs_size >= 2)
                {
                    Cv2.ImShow("2", out_img2);
                }

                if (out_imgs_size >= 3)
                {
                    Cv2.ImShow("3", out_img3);
                }

                textBox1.Text = $"耗时:{costTime:F2}ms";
            }
            else
            {
                textBox1.Text = "识别失败";
            }
            button2.Enabled = true;
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            destroy(engine);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (pictureBox2.Image == null)
            {
                return;
            }
            Bitmap output = new Bitmap(pictureBox2.Image);
            var sdf = new SaveFileDialog();
            sdf.Title = "保存";
            sdf.Filter = "Images (*.jpg)|*.jpg|Images (*.png)|*.png|Images (*.bmp)|*.bmp";
            if (sdf.ShowDialog() == DialogResult.OK)
            {
                switch (sdf.FilterIndex)
                {
                    case 1:
                        {
                            output.Save(sdf.FileName, ImageFormat.Jpeg);
                            break;
                        }
                    case 2:
                        {
                            output.Save(sdf.FileName, ImageFormat.Png);
                            break;
                        }
                    case 3:
                        {
                            output.Save(sdf.FileName, ImageFormat.Bmp);
                            break;
                        }
                }
                MessageBox.Show("保存成功,位置:" + sdf.FileName);
            }

        }
    }
}

下载

源码下载

参考

https://github.com/hpc203/TableDetection

相关推荐
兰亭妙微18 小时前
用户体验的真正边界在哪里?对的 “认知负荷” 设计思考
人工智能·ux
13631676419侯18 小时前
智慧物流与供应链追踪
人工智能·物联网
TomCode先生18 小时前
MES 离散制造核心流程详解(含关键动作、角色与异常处理)
人工智能·制造·mes
zd20057218 小时前
AI辅助数据分析和学习了没?
人工智能·学习
johnny23318 小时前
强化学习RL
人工智能
乌恩大侠18 小时前
无线网络规划与优化方式的根本性变革
人工智能·usrp
放羊郎18 小时前
基于萤火虫+Gmapping、分层+A*优化的导航方案
人工智能·slam·建图·激光slam
王哈哈^_^19 小时前
【数据集+完整源码】水稻病害数据集,yolov8水稻病害检测数据集 6715 张,目标检测水稻识别算法实战训推教程
人工智能·算法·yolo·目标检测·计算机视觉·视觉检测·毕业设计
SEOETC19 小时前
数字人技术:虚实交融的未来图景正在展开
人工智能
boonya19 小时前
从阿里云大模型服务平台百炼看AI应用集成与实践
人工智能·阿里云·云计算