C# Onnx实现特征匹配DeDoDe检测

 更新时间:2023年11月22日 10:53:04   作者:天天代码码天天  
这篇文章主要为大家详细介绍了C# Onnx如何实现特征匹配DeDoDe检测,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下

介绍

github地址:https://github.com/Parskatt/DeDoDe

DeDoDe 🎶 Detect, Don't Describe - Describe, Don't Detect, for Local Feature Matching

The DeDoDe detector learns to detect 3D consistent repeatable keypoints, which the DeDoDe descriptor learns to match. The result is a powerful decoupled local feature matcher.

Training DeDoDe

DISCLAMER: I've (Johan) not yet tested that the training scripts here reproduces our original results. This repo is very similar to the internal training repo, but there might be bugs introduced by refactoring etc. Let me know if you face any issues reproducing our results (or if you somehow get better results :D).

See experiments for the scripts to train DeDoDe. We trained on a single A100-40GB with a batchsize of 8. Note that you need to do the data prep first, see data_prep.

As usual, we require that you have the MegaDepth dataset already downloaded, and that you have the prepared scene info from DKM.

效果

模型信息

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

Outputs
-------------------------
name:matches_A
tensor:Float[-1, -1]
name:matches_B
tensor:Float[-1, -1]
name:batch_ids
tensor:Int64[-1]
---------------------------------------------------------------

项目

VS2022

.net framework 4.8

OpenCvSharp 4.8

Microsoft.ML.OnnxRuntime 1.16.2

代码

using Microsoft.ML.OnnxRuntime.Tensors;
using Microsoft.ML.OnnxRuntime;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Linq;
using System.Drawing;
using static System.Net.Mime.MediaTypeNames;
using System.Numerics;
 
namespace Onnx_Demo
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }
 
        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string image_path = "";
        string image_path2 = "";
 
        DateTime dt1 = DateTime.Now;
        DateTime dt2 = DateTime.Now;
 
        int inpWidth;
        int inpHeight;
 
        float[] mean =new float[] { 0.485f, 0.456f, 0.406f };
        float[] std = new float[] { 0.229f, 0.224f, 0.225f };
 
        Mat image;
        Mat image2;
 
        string model_path = "";
 
        SessionOptions options;
        InferenceSession onnx_session;
        Tensor<float> input_tensor;
        Tensor<float> mask_tensor;
        List<NamedOnnxValue> input_ontainer;
 
        IDisposableReadOnlyCollection<DisposableNamedOnnxValue> result_infer;
        DisposableNamedOnnxValue[] results_onnxvalue;
 
        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 System.Drawing.Bitmap(image_path);
            image = new Mat(image_path);
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            // 创建输入容器
            input_ontainer = new List<NamedOnnxValue>();
 
            // 创建输出会话
            options = new SessionOptions();
            options.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_INFO;
            options.AppendExecutionProvider_CPU(0);// 设置为CPU上运行
 
            // 创建推理模型类,读取本地模型文件
            model_path = "model/dedode_end2end_1024.onnx";
 
            inpHeight = 256;
            inpWidth = 256;
 
            onnx_session = new InferenceSession(model_path, options);
 
            // 创建输入容器
            input_ontainer = new List<NamedOnnxValue>();
 
            image_path = "test_img/im_A.jpg";
            pictureBox1.Image = new Bitmap(image_path);
 
            image_path2 = "test_img/im_B.jpg";
            pictureBox3.Image = new Bitmap(image_path2);
 
        }
 
        private unsafe void button2_Click(object sender, EventArgs e)
        {
            if (image_path == "")
            {
                return;
            }
            textBox1.Text = "检测中,请稍等……";
            pictureBox2.Image = null;
            System.Windows.Forms.Application.DoEvents();
 
            image = new Mat(image_path);
            image2 = new Mat(image_path2);
 
            float[] input_tensor_data = new float[2 * 3 * inpWidth * inpHeight];
 
            //preprocess
            Mat dstimg = new Mat();
            Cv2.CvtColor(image, dstimg, ColorConversionCodes.BGR2RGB);
            Cv2.Resize(dstimg, dstimg, new OpenCvSharp.Size(inpWidth, inpHeight));
            for (int c = 0; c < 3; c++)
            {
                for (int i = 0; i < inpHeight; i++)
                {
                    for (int j = 0; j < inpWidth; j++)
                    {
                        float pix = ((byte*)(dstimg.Ptr(i).ToPointer()))[j * 3 + c];
                        input_tensor_data[c * inpWidth * inpHeight + i * inpWidth + j] = (float)((pix / 255.0 - mean[c]) / std[c]);
                    }
                }
            }
 
            Cv2.CvtColor(image2, dstimg, ColorConversionCodes.BGR2RGB);
            Cv2.Resize(dstimg, dstimg, new OpenCvSharp.Size(inpWidth, inpHeight));
            for (int c = 0; c < 3; c++)
            {
                for (int i = 0; i < inpHeight; i++)
                {
                    for (int j = 0; j < inpWidth; j++)
                    {
                        float pix = ((byte*)(dstimg.Ptr(i).ToPointer()))[j * 3 + c];
                        input_tensor_data[(3+c )* inpWidth * inpHeight + i * inpWidth + j] = (float)((pix / 255.0 - mean[c]) / std[c]);
                    }
                }
            }
 
            input_tensor = new DenseTensor<float>(input_tensor_data, new[] { 2, 3, inpHeight, inpWidth });
 
            //将 input_tensor 放入一个输入参数的容器,并指定名称
            input_ontainer.Add(NamedOnnxValue.CreateFromTensor("images", input_tensor));
 
            dt1 = DateTime.Now;
            //运行 Inference 并获取结果
            result_infer = onnx_session.Run(input_ontainer);
            dt2 = DateTime.Now;
 
            //Postprocessing
            //将输出结果转为DisposableNamedOnnxValue数组
            results_onnxvalue = result_infer.ToArray();
 
            float[] matches_A = results_onnxvalue[0].AsTensor<float>().ToArray();
            float[] matches_B = results_onnxvalue[1].AsTensor<float>().ToArray();
            int num_points = results_onnxvalue[0].AsTensor<float>().Dimensions[0];
 
            List<KeyPoint> points_A = new List<KeyPoint>();
            List<KeyPoint> points_B = new List<KeyPoint>();
 
            KeyPoint temp;
            for (int i = 0; i < num_points; i++)
            {
                temp = new KeyPoint();
                temp.Pt.X = (float)((matches_A[i * 2] + 1) * 0.5 * image.Cols);
                temp.Pt.Y = (float)((matches_A[i * 2 + 1] + 1) * 0.5 * image.Rows);
                temp.Size = 1f;
                points_A.Add(temp);
            }
 
            num_points = results_onnxvalue[1].AsTensor<float>().Dimensions[0];
            for (int i = 0; i < num_points; i++)
            {
                temp = new KeyPoint();
                temp.Pt.X = (float)((matches_B[i * 2] + 1) * 0.5 * image2.Cols);
                temp.Pt.Y = (float)((matches_B[i * 2 + 1] + 1) * 0.5 * image2.Rows);
                temp.Size = 1f;
                points_B.Add(temp);
            }
 
            //匹配结果放在matches里面
            num_points = points_A.Count();
            List<DMatch> matches=new List<DMatch>();
            for (int i = 0; i < num_points; i++)
            {
                matches.Add(new DMatch(i, i, 0f));
            }
 
            //按照匹配关系将图画出来,背景图为match_img
            Mat match_img = new Mat();
            Cv2.DrawMatches(image, points_A, image2, points_B, matches, match_img);
 
            pictureBox2.Image = new System.Drawing.Bitmap(match_img.ToMemoryStream());
            textBox1.Text = "推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms";
 
        }
 
        private void pictureBox2_DoubleClick(object sender, EventArgs e)
        {
            Common.ShowNormalImg(pictureBox2.Image);
        }
 
        private void button3_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;
 
            pictureBox3.Image = null;
            pictureBox2.Image = null;
            textBox1.Text = "";
 
            image_path2 = ofd.FileName;
            pictureBox3.Image = new System.Drawing.Bitmap(image_path2);
            image2 = new Mat(image_path2);
        }
 
        private void pictureBox3_DoubleClick(object sender, EventArgs e)
        {
            Common.ShowNormalImg(pictureBox3.Image);
        }
 
        private void pictureBox1_DoubleClick(object sender, EventArgs e)
        {
            Common.ShowNormalImg(pictureBox1.Image);
        }
    }
}

到此这篇关于C# Onnx实现特征匹配DeDoDe检测的文章就介绍到这了,更多相关C# Onnx特征匹配内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • c#中DateTime.Now函数的使用详解

    c#中DateTime.Now函数的使用详解

    本篇文章对c#中DateTime.Now函数的使用进行了介绍。需要的朋友参考下
    2013-05-05
  • 微信开发--企业转账到用户

    微信开发--企业转账到用户

    本文主要介绍了微信开发--企业转账到用户的实现方法与步骤。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • C#编写游戏客户端的实现代码

    C#编写游戏客户端的实现代码

    这篇文章主要介绍了C#编写游戏客户端的实现代码,连接客户端原理流程图,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • C#实现金额转换成中文大写金额

    C#实现金额转换成中文大写金额

    这篇文章主要为大家详细介绍了C#实现金额转换成中文大写金额,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • C# DirectShow预览摄像头并截图

    C# DirectShow预览摄像头并截图

    这篇文章主要为大家详细介绍了C# DirectShow预览摄像头并截图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • 浅谈c#中config.exe 引发的一些问题

    浅谈c#中config.exe 引发的一些问题

    下面小编就为大家分享一篇浅谈c#中config.exe 引发的一些问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-11-11
  • C# WinForm RichTextBox文本动态滚动显示文本方式

    C# WinForm RichTextBox文本动态滚动显示文本方式

    这篇文章主要介绍了C# WinForm RichTextBox文本动态滚动显示文本方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • C#使用 NAudio 实现音频可视化的方法

    C#使用 NAudio 实现音频可视化的方法

    这篇文章主要介绍了[C#] 使用 NAudio 实现音频可视化的相关资料,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-05-05
  • c#实现多线程局域网聊天系统

    c#实现多线程局域网聊天系统

    这篇文章主要介绍了c#实现多线程局域网聊天系统的相关代码,有此方面需求的小伙伴可以参考下。
    2015-06-06
  • 详解C#如何使用消息队列MSMQ

    详解C#如何使用消息队列MSMQ

    消息队列 (MSMQ Microsoft Message Queuing)是MS提供的服务,也就是Windows操作系统的功能,下面就跟随小编一起了解一下C#中是如何使用消息队列MSMQ的吧
    2024-01-01

最新评论