• C# Onnx 轻量实时的M-LSD直线检测


    目录

    介绍

    效果

    效果1

    效果2

    效果3

    效果4

    模型信息

    项目

    代码

    下载

    其他


    介绍

    github地址:https://github.com/navervision/mlsd 

    M-LSD: Towards Light-weight and Real-time Line Segment Detection
    Official Tensorflow implementation of "M-LSD: Towards Light-weight and Real-time Line Segment Detection" (AAAI 2022 Oral session)

    Geonmo Gu*, Byungsoo Ko*, SeoungHyun Go, Sung-Hyun Lee, Jingeun Lee, Minchul Shin (* Authors contributed equally.)

    First figure: Comparison of M-LSD and existing LSD methods on GPU. Second figure: Inference speed and memory usage on mobile devices.

    We present a real-time and light-weight line segment detector for resource-constrained environments named Mobile LSD (M-LSD). M-LSD exploits extremely efficient LSD architecture and novel training schemes, including SoL augmentation and geometric learning scheme. Our model can run in real-time on GPU, CPU, and even on mobile devices.

    效果

    效果1

    效果2

    效果3

    效果4

    模型信息

    Inputs
    -------------------------
    name:input_image_with_alpha:0
    tensor:Float[1, 512, 512, 4]
    ---------------------------------------------------------------

    Outputs
    -------------------------
    name:Identity
    tensor:Int32[1, 200, 2]
    name:Identity_1
    tensor:Float[1, 200]
    name:Identity_2
    tensor:Float[1, 256, 256, 4]
    ---------------------------------------------------------------

    项目

    VS2022

    .net framework 4.8

    OpenCvSharp 4.8

    Microsoft.ML.OnnxRuntime 1.16.2

    代码

    1. using Microsoft.ML.OnnxRuntime.Tensors;
    2. using Microsoft.ML.OnnxRuntime;
    3. using OpenCvSharp;
    4. using System;
    5. using System.Collections.Generic;
    6. using System.Windows.Forms;
    7. using System.Linq;
    8. using System.Drawing;
    9. namespace Onnx_Demo
    10. {
    11. public partial class frmMain : Form
    12. {
    13. public frmMain()
    14. {
    15. InitializeComponent();
    16. }
    17. string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
    18. string image_path = "";
    19. DateTime dt1 = DateTime.Now;
    20. DateTime dt2 = DateTime.Now;
    21. int inpWidth;
    22. int inpHeight;
    23. Mat image;
    24. string model_path = "";
    25. SessionOptions options;
    26. InferenceSession onnx_session;
    27. Tensor<float> input_tensor;
    28. Tensor<float> mask_tensor;
    29. List<NamedOnnxValue> input_ontainer;
    30. IDisposableReadOnlyCollection<DisposableNamedOnnxValue> result_infer;
    31. DisposableNamedOnnxValue[] results_onnxvalue;
    32. float conf_threshold = 0.5f;
    33. float dist_threshold = 20.0f;
    34. private void button1_Click(object sender, EventArgs e)
    35. {
    36. OpenFileDialog ofd = new OpenFileDialog();
    37. ofd.Filter = fileFilter;
    38. if (ofd.ShowDialog() != DialogResult.OK) return;
    39. pictureBox1.Image = null;
    40. pictureBox2.Image = null;
    41. textBox1.Text = "";
    42. image_path = ofd.FileName;
    43. pictureBox1.Image = new System.Drawing.Bitmap(image_path);
    44. image = new Mat(image_path);
    45. }
    46. private void Form1_Load(object sender, EventArgs e)
    47. {
    48. // 创建输入容器
    49. input_ontainer = new List<NamedOnnxValue>();
    50. // 创建输出会话
    51. options = new SessionOptions();
    52. options.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_INFO;
    53. options.AppendExecutionProvider_CPU(0);// 设置为CPU上运行
    54. // 创建推理模型类,读取本地模型文件
    55. model_path = "model/model_512x512_large.onnx";
    56. inpWidth = 512;
    57. inpHeight = 512;
    58. onnx_session = new InferenceSession(model_path, options);
    59. // 创建输入容器
    60. input_ontainer = new List<NamedOnnxValue>();
    61. image_path = "test_img/4.jpg";
    62. pictureBox1.Image = new Bitmap(image_path);
    63. }
    64. private unsafe void button2_Click(object sender, EventArgs e)
    65. {
    66. if (image_path == "")
    67. {
    68. return;
    69. }
    70. textBox1.Text = "检测中,请稍等……";
    71. pictureBox2.Image = null;
    72. System.Windows.Forms.Application.DoEvents();
    73. image = new Mat(image_path);
    74. Mat resize_image = new Mat();
    75. Cv2.Resize(image, resize_image, new OpenCvSharp.Size(512, 512));
    76. float h_ratio = (float)image.Rows / 512;
    77. float w_ratio = (float)image.Cols / 512;
    78. int row = resize_image.Rows;
    79. int col = resize_image.Cols;
    80. float[] input_tensor_data = new float[1 * 4 * row * col];
    81. int k = 0;
    82. for (int i = 0; i < row; i++)
    83. {
    84. for (int j = 0; j < col; j++)
    85. {
    86. for (int c = 0; c < 3; c++)
    87. {
    88. float pix = ((byte*)(resize_image.Ptr(i).ToPointer()))[j * 3 + c];
    89. input_tensor_data[k] = pix;
    90. k++;
    91. }
    92. input_tensor_data[k] = 1;
    93. k++;
    94. }
    95. }
    96. input_tensor = new DenseTensor<float>(input_tensor_data, new[] { 1, 512, 512, 4 });
    97. //input_tensor 放入一个输入参数的容器,并指定名称
    98. input_ontainer.Add(NamedOnnxValue.CreateFromTensor("input_image_with_alpha:0", input_tensor));
    99. dt1 = DateTime.Now;
    100. //运行 Inference 并获取结果
    101. result_infer = onnx_session.Run(input_ontainer);
    102. dt2 = DateTime.Now;
    103. //将输出结果转为DisposableNamedOnnxValue数组
    104. results_onnxvalue = result_infer.ToArray();
    105. int[] pts = results_onnxvalue[0].AsTensor<int>().ToArray();
    106. float[] pts_score = results_onnxvalue[1].AsTensor<float>().ToArray();
    107. float[] vmap = results_onnxvalue[2].AsTensor<float>().ToArray();
    108. List<List<int>> segments_list = new List>();
    109. int num_lines = 200;
    110. int map_h = 256;
    111. int map_w = 256;
    112. for (int i = 0; i < num_lines; i++)
    113. {
    114. int y = pts[i * 2];
    115. int x = pts[i * 2 + 1];
    116. float disp_x_start = vmap[0 + y * map_w * 4 + x * 4];
    117. float disp_y_start = vmap[1 + y * map_w * 4 + x * 4];
    118. float disp_x_end = vmap[2 + y * map_w * 4 + x * 4];
    119. float disp_y_end = vmap[3 + y * map_w * 4 + x * 4];
    120. float distance = (float)Math.Sqrt(Math.Pow(disp_x_start - disp_x_end, 2) + Math.Pow(disp_y_start - disp_y_end, 2));
    121. if (pts_score[i] > conf_threshold && distance > dist_threshold)
    122. {
    123. float x_start = (x + disp_x_start) * 2 * w_ratio;
    124. float y_start = (y + disp_y_start) * 2 * h_ratio;
    125. float x_end = (x + disp_x_end) * 2 * w_ratio;
    126. float y_end = (y + disp_y_end) * 2 * h_ratio;
    127. List<int> line = new List<int>() { (int)x_start, (int)y_start, (int)x_end, (int)y_end };
    128. segments_list.Add(line);
    129. }
    130. }
    131. Mat result_image = image.Clone();
    132. for (int i = 0; i < segments_list.Count; i++)
    133. {
    134. Cv2.Line(result_image, new OpenCvSharp.Point(segments_list[i][0], segments_list[i][1]), new OpenCvSharp.Point(segments_list[i][2], segments_list[i][3]), new Scalar(0, 0, 255), 3);
    135. }
    136. pictureBox2.Image = new System.Drawing.Bitmap(result_image.ToMemoryStream());
    137. textBox1.Text = "推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms";
    138. }
    139. private void pictureBox2_DoubleClick(object sender, EventArgs e)
    140. {
    141. Common.ShowNormalImg(pictureBox2.Image);
    142. }
    143. private void pictureBox1_DoubleClick(object sender, EventArgs e)
    144. {
    145. Common.ShowNormalImg(pictureBox1.Image);
    146. }
    147. }
    148. }

    下载

    源码下载

    其他

    结合透视变换可实现图像校正,图像校正参考

    C# OpenCvSharp 图像校正_天天代码码天天的博客-CSDN博客

    C# OpenCvSharp 透视变换(图像摆正)Demo-CSDN博客

  • 相关阅读:
    算法金 | Transformer,一个神奇的算法模型!!
    Vue3中diff算法比对新老节点孩子数组
    解析紫光展锐T820 5G芯片——让照片接近原色
    41-MybatisPlus
    强化学习-策略梯度和PPO
    前端国密SM4加密代码
    OpenAI GPT-4.5 Turbo 泄露,六月或将发布
    【头歌实验】一、Python初体验——Hello World
    K8S pod资源、探针
    【学生网页设计作品 】关于HTML公益主题网页设计——谨防电信诈骗网
  • 原文地址:https://blog.csdn.net/lw112190/article/details/134411886