C# Onnx Ultra-Fast-Lane-Detection-v2 车道线检测

news2025/7/15 11:26:44

效果

项目

代码

using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

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

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

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

        Mat image;
        Mat result_image;

        SessionOptions options;
        InferenceSession onnx_session;
        Tensor<float> input_tensor;
        List<NamedOnnxValue> input_ontainer;
        IDisposableReadOnlyCollection<DisposableNamedOnnxValue> result_infer;
        DisposableNamedOnnxValue[] results_onnxvalue;

        StringBuilder sb = new StringBuilder();

        int inpHeight = 320;
        int inpWidth = 1600;

        int num_row;
        int num_col;
        List<float> row_anchor = new List<float>();
        List<float> col_anchor = new List<float>();
        float crop_ratio;
        string dataset;

        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)
        {
            startupPath = Application.StartupPath + "\\model\\";

            model_path = startupPath + "ufldv2_culane_res18_320x1600.onnx";

            // 创建输出会话
            options = new SessionOptions();
            options.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_INFO;
            options.AppendExecutionProvider_CPU(0);// 设置为CPU上运行

            // 创建推理模型类,读取本地模型文件
            onnx_session = new InferenceSession(model_path, options);

            if (model_path.Contains("culane"))
            {
                dataset = "culane";
                num_row = 72;
                num_col = 81;
                crop_ratio = 0.6f;
            }
            else
            {
                num_row = 56;
                num_col = 41;
                crop_ratio = 0.8f;
            }

            // 创建输入容器
            input_ontainer = new List<NamedOnnxValue>();

            GenerateAnchor();

        }

        void GenerateAnchor()
        {
            for (int i = 0; i < num_row; i++)
            {
                if (dataset == "culane")
                {
                    row_anchor.Add((float)(0.42 + i * (1.0 - 0.42) / (num_row - 1)));
                }
                else
                {
                    row_anchor.Add((float)((160 + i * (710 - 160) / (num_row - 1)) / 720.0));
                }
            }
            for (int i = 0; i < num_col; i++)
            {
                col_anchor.Add((float)(0.0 + i * (1.0 - 0.0) / (num_col - 1)));
            }
        }

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

            //图片
            image = new Mat(image_path);

            int img_h = image.Rows;
            int img_w = image.Cols;
            Mat resize_image = new Mat();

            Cv2.Resize(image, resize_image, new OpenCvSharp.Size(inpWidth, inpHeight / crop_ratio));

            Mat dstimg = Common.Normalize(resize_image,inpHeight);

            var sourceData = Common.ExtractMat(dstimg);
            int[] dimensions = new int[4] { 1, 3, inpHeight, inpWidth };
            input_tensor = new DenseTensor<float>(sourceData, dimensions);

            input_ontainer.Add(NamedOnnxValue.CreateFromTensor("input", input_tensor));

            dt1 = DateTime.Now;
            //运行 Inference 并获取结果
            result_infer = onnx_session.Run(input_ontainer);
            dt2 = DateTime.Now;

            //将输出结果转为DisposableNamedOnnxValue数组
            results_onnxvalue = result_infer.ToArray();

            var loc_row = results_onnxvalue[0].AsTensor<float>().ToArray();
            var loc_col = results_onnxvalue[1].AsTensor<float>().ToArray();
            var exist_row = results_onnxvalue[2].AsTensor<float>().ToArray();
            var exist_col = results_onnxvalue[3].AsTensor<float>().ToArray();

            var loc_row_dims = results_onnxvalue[0].AsTensor<float>().Dimensions.ToArray();
            int num_grid_row = loc_row_dims[1];
            int num_cls_row = loc_row_dims[2];
            int num_lane_row = loc_row_dims[3];

            var loc_col_dims = results_onnxvalue[1].AsTensor<float>().Dimensions.ToArray();
            int num_grid_col = loc_col_dims[1];
            int num_cls_col = loc_col_dims[2];
            int num_lane_col = loc_col_dims[3];

            int[] exist_row_dims = results_onnxvalue[2].AsTensor<float>().Dimensions.ToArray();
            int[] exist_col_dims = results_onnxvalue[3].AsTensor<float>().Dimensions.ToArray();

            int[] max_indices_row = Common.argmax_1(loc_row, loc_row_dims);
            int[] valid_row = Common.argmax_1(exist_row, exist_row_dims);
            int[] max_indices_col = Common.argmax_1(loc_col, loc_col_dims);
            int[] valid_col = Common.argmax_1(exist_col, exist_col_dims);

            List<List<OpenCvSharp.Point>> line_list = new List<List<OpenCvSharp.Point>>();
            List<OpenCvSharp.Point> temp = new List<OpenCvSharp.Point>();
            line_list.Add(temp);
            line_list.Add(temp);
            line_list.Add(temp);
            line_list.Add(temp);

            int[] item = new int[2] { 1, 2 };

            foreach (var i in item)
            {
                if (Common.sum_valid(valid_row, num_cls_row, num_lane_row, i) > num_cls_row * 0.5)
                {
                    for (int k = 0; k < num_cls_row; k++)
                    {
                        int index = k * num_lane_row + i;
                        if (valid_row[index] != 0)
                        {
                            List<float> pred_all_list = new List<float>();
                            List<int> all_ind_list = new List<int>();
                            for (int all_ind = Math.Max(0, (int)(max_indices_row[index] - 1)); all_ind <= (Math.Min(num_grid_row - 1, max_indices_row[index]) + 1); all_ind++)
                            {
                                pred_all_list.Add(loc_row[all_ind * num_cls_row * num_lane_row + index]);
                                all_ind_list.Add(all_ind);
                            }

                            List<float> pred_all_list_softmax = new List<float>();
                            float[] pred_all_list_softmax_temp = new float[pred_all_list.Count];
                            Common.SoftMaxFast(pred_all_list.ToArray(), ref pred_all_list_softmax_temp, pred_all_list.Count);
                            pred_all_list_softmax = pred_all_list_softmax_temp.ToList();

                            float out_temp = 0;

                            for (int l = 0; l < pred_all_list.Count; l++)
                            {
                                out_temp += pred_all_list_softmax[l] * all_ind_list[l];
                            }
                            float x = (float)((out_temp + 0.5) / (num_grid_row - 1.0));
                            float y = row_anchor[k];
                            line_list[i].Add(new OpenCvSharp.Point((int)(x * img_w), (int)(y * img_h)));
                        }
                    }
                }
            }

            item = new int[4] { 0, 1, 2, 3 };
            foreach (var i in item)
            {
                if (Common.sum_valid(valid_col, num_cls_col, num_lane_col, i) > num_cls_col / 4)
                {
                    for (int k = 0; k < num_cls_col; k++)
                    {
                        int index = k * num_lane_col + i;
                        if (valid_col[index] != 0)
                        {
                            List<float> pred_all_list = new List<float>();
                            List<int> all_ind_list = new List<int>();
                            for (int all_ind = Math.Max(0, (int)(max_indices_col[index] - 1)); all_ind <= (Math.Min(num_grid_col - 1, max_indices_col[index]) + 1); all_ind++)
                            {
                                pred_all_list.Add(loc_col[all_ind * num_cls_col * num_lane_col + index]);
                                all_ind_list.Add(all_ind);
                            }

                            List<float> pred_all_list_softmax = new List<float>();
                            float[] pred_all_list_softmax_temp = new float[pred_all_list.Count];
                            Common.SoftMaxFast(pred_all_list.ToArray(), ref pred_all_list_softmax_temp, pred_all_list.Count);
                            pred_all_list_softmax = pred_all_list_softmax_temp.ToList();

                            float out_temp = 0;
                            for (int l = 0; l < pred_all_list.Count; l++)
                            {
                                out_temp += pred_all_list_softmax[l] * all_ind_list[l];
                            }
                            float y = (float)((out_temp + 0.5) / (num_grid_col - 1.0));
                            float x = col_anchor[k];
                            line_list[i].Add(new OpenCvSharp.Point((int)(x * img_w), (int)(y * img_h)));
                        }
                    }
                }
            }

            result_image = image.Clone();

            foreach (var line in line_list)
            {
                foreach (var p in line)
                {
                    Cv2.Circle(result_image, p, 3, new Scalar(0, 255, 0), -1);
                }
            }

            sb.Clear();
            sb.AppendLine("推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms");
            sb.AppendLine("------------------------------");

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

            textBox1.Text = sb.ToString();
        }

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

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

下载

源码下载

ufldv2-culane-res34-320x1600.onnx

ufldv2-tusimple-res18-320x800.onnx

ufldv2-tusimple-res34-320x800.onnx

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

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

相关文章

最新ai系统ChatGPT程序源码+详细搭建教程+以图生图+Dall-E2绘画+支持GPT4+Midjourney绘画

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

高频SQL50题(基础版)-1

文章目录 主要内容一.SQL练习题1.1757-可回收且抵制的产品代码如下&#xff08;示例&#xff09;: 2.584-寻找用户推荐人代码如下&#xff08;示例&#xff09;: 3.595-大的国家代码如下&#xff08;示例&#xff09;: 4.1148-文章浏览代码如下&#xff08;示例&#xff09;: 5…

「2023·最新盘点」十大热门WebStorm主题

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。被广大中国JS开发者誉为"Web前端开发神器""最强大的HTML5编辑器""最智能的JavaSscript IDE"等。与IntelliJ IDEA同源&#xff0c;继承了IntelliJ IDEA强大的JS部分的功能。 WebStorm v20…

前聚美优品运维负责人谈CMDB

导读CMDB大家并不陌生&#xff0c;在运维的工作中几乎都会用到CMDB&#xff0c;在聚美内部我们也称它为资产系统&#xff0c;管理整个服务器的资产&#xff0c;当然也包括一些配置上的变更。 讲师介绍 张川&#xff0c;前聚美优品运维负责人。任职聚美优品四年间&#xff0c;负…

Brox光流法公式推导

第1章 数学基础 Brox光流法使用变分方法求解,得到使总能量最小的流场。涉及到的数学概念及工具包含:微分,变分,泛函,Euler-Lagrange equation。 1.1. 函数及微分 微分是微积分的一个基本概念,它用于描述函数在某一点附近的变化率。在物理学和工程学中,微分常被用来描…

基于Taro + React 实现微信小程序半圆滑块组件、半圆进度条、弧形进度条、半圆滑行轨道(附源码)

效果&#xff1a; 功能点&#xff1a; 1、四个档位 2、可点击加减切换档位 3、可以点击区域切换档位 4、可以滑动切换档位 目的&#xff1a; 给大家提供一些实现思路&#xff0c;找了一圈&#xff0c;一些文章基本不能直接用&#xff0c;错漏百出&#xff0c;代码还藏着掖…

[极客大挑战 2019]Secret File 1

题目环境&#xff1a; 网页什么都没有&#xff0c;GET那里也没有任何参数和文件 F12查看隐藏文件发现隐藏文件点进去看看发现一个可点击按钮SECRET 好家伙&#xff0c;什么都没有 这里猜测还有隐藏文件目录扫描使用工具dirsearch命令&#xff1a;python dirsearch.py -u [http:…

LLaMA-Adapter源码解析

LLaMA-Adapter源码解析 伪代码 def transformer_block_with_llama_adapter(x, gating_factor, soft_prompt):residual xy zero_init_attention(soft_prompt, x) # llama-adapter: prepend prefixx self_attention(x)x x gating_factor * y # llama-adapter: apply zero_init…

全网公开电商数据的采集重点

数据的采集是根据需求而定的&#xff0c;品牌会做数据采集的原因&#xff0c;一般与内部营销、渠道管控有关&#xff0c;如需要做价格管控时&#xff0c;需要先采集价格&#xff0c;这就需要对数据进行采集&#xff0c;包括价格、促销信息&#xff0c;又或者是需要做行业分析、…

总感觉戴助听器耳朵又闷又堵怎么办?

随着助听器技术的进步发展&#xff0c;这些问题都有了一定程度的改善。例如&#xff0c;现在的助听器变得越来越小巧&#xff0c;外形更加美观和隐蔽&#xff1b;各种降噪技术和验配技巧也提升了助听器的音质和清晰度。 但是&#xff0c;还有一个问题困扰着很多助听器用户&…

缓存击穿只会逻辑过期 OR 互斥锁?深入思考 == 鹤立鸡群

网上但凡看得见的文章&#xff0c;大部分在说缓存穿透时都是无脑分布式锁 / 逻辑过期&#xff0c;分布式锁一点问题都没有么&#xff1f;逻辑过期一点问题都没有么&#xff1f;还能不能再进一步优化&#xff1f; 在聊聊缓存击穿的双重判定锁之前&#xff0c;我们将按照循循渐进…

java基础之IO操作

用户进程发起请求&#xff0c;内核接收到请求后&#xff0c;从I/O设备中获取数据到buffer中&#xff0c;再将buffer中的数据copy到用户进程的地址空间&#xff0c;该用户进程获取到数据后再响应客户端。 数据输入到buffer需要时间&#xff0c;从buffer复制数据至进程也需要时间…

社区参展招募| 与新兴初创企业一起!

一般来说&#xff0c;创业公司的生存率较低&#xff0c;失败率较高。根据不同的数据来源&#xff0c;创业公司的失败率高达 80%-90%。据统计&#xff0c;在中国每年新注册的企业数量超过 100 万家&#xff0c;但能够存活到 5 年以上的企业不足 7%&#xff0c;10 年以上不足 2%。…

路径复杂度(环形回路的复杂度计算)

路径复杂度 1、通用公式: (EF) - N12、非环形回路的复杂度计算公式为什么1&#xff1f;公式为什么(EF)-N&#xff1f; 3、类推到环形回路的复杂度演示区分下纯环形回路 和 不是纯粹的环形回路 3、特殊情况&#xff1a;自旋公式化理解&#xff1a;此时将B自旋回路看成一个环形回…

混合编程 ATPCS规范及案例(汇编调用C、C调用汇编、内联汇编)

1.混合编程的规范 2.汇编调用C 2.C调用汇编 3.内联汇编 例子&#xff1a;

高速视觉筛选机PCIe实时运动控制卡XPCIE1028亮相深圳慕尼黑华南电子展

本次的深圳慕尼黑华南电子展正运动技术将携高速视觉筛选机PCIe实时运动控制卡XPCIE1028亮相。此外&#xff0c;我们还为您准备了的新互动模式&#xff0c;您将有机会赢得超值礼品&#xff01; 产品导读 正运动技术的PCI Express总线运动控制卡XPCIE1028&#xff0c;具备位置…

二叉树初次的整体过程

1.计算二叉树节点的范围 2.计算用父亲下标找出儿子的下标&#xff0c;用儿子的下标找出父亲的下标方法 2.向下调整算法 void AdjustUp(HPDataType*a,int child) {int parent (child - 1) / 2;while (0 < child){if (a[child] < a[parent]){HPDataType* tem a[child];a[…

Linux常用命令——chgrp命令

在线Linux命令查询工具 chgrp 用来变更文件或目录的所属群组 补充说明 chgrp命令用来改变文件或目录所属的用户组。该命令用来改变指定文件所属的用户组。其中&#xff0c;组名可以是用户组的id&#xff0c;也可以是用户组的组名。文件名可以 是由空格分开的要改变属组的文…

mpp解码详解

解码器数据流接口 一. decode_put_packet 输入码流的形式&#xff1a;分帧与不分帧 MPP 的输入都是没有封装信息的裸码流&#xff0c;裸码流输入有两种形式&#xff1a; 不分帧 这种方式是已经按帧分段的数据&#xff0c;即每一包输入给 decode_put_packet 函数的 MppPacket 数…

PCIe 的 MSI 中断详解,寄存器级别的详细流程分析,完全搞懂硬件的工作流程

PCIe 的 MSI 中断 前言 什么是 MSI 中断 (Message Signaled Interrupts) 概念与内容介绍待补充 正文 对 EP 的初始化 需要对 EP 的配置空间 MSI 相关功能的寄存器进行初始化&#xff0c;主要有两个寄存器 Message Address 和 Message Data。它们分别的含义是 EP 产生 MSI …