C# OnnxRuntime 部署 DAViD 深度估计

C# OnnxRuntime 部署 DAViD 深度估计
目录说明效果模型信息项目代码说明官网地址https://github.com/microsoft/DAViD效果模型信息Model Properties ------------------------- metadata{} --------------------------------------------------------------- Inputs ------------------------- nameinput tensorFloat[-1, 3, 512, 512] --------------------------------------------------------------- Outputs ------------------------- nameoutput tensorFloat[-1, 512, 512] ---------------------------------------------------------------项目代码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.Windows.Forms; namespace Onnx_Demo { public partial class Form1 : Form { // ----- 深度估计专用字段 ----- string fileFilter *.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.png; string image_path ; string startupPath; DateTime dt1 DateTime.Now; DateTime dt2 DateTime.Now; string model_path; Mat image; // 原始图像BGR Mat depth_color_map; // 生成的深度彩色图 SessionOptions options; InferenceSession onnx_session; Tensorfloat input_tensor; ListNamedOnnxValue input_container; IDisposableReadOnlyCollectionDisposableNamedOnnxValue result_infer; int inpHeight 512, inpWidth 512; bool inverse_depth false; // 是否反转深度近处亮 public Form1() { InitializeComponent(); } // ----- 按钮1选择图片 ----- private void button1_Click(object sender, EventArgs e) { OpenFileDialog ofd new OpenFileDialog(); ofd.Filter fileFilter; if (ofd.ShowDialog() ! DialogResult.OK) return; pictureBox1.Image null; image_path ofd.FileName; pictureBox1.Image new Bitmap(image_path); textBox1.Text ; image new Mat(image_path); pictureBox2.Image null; depth_color_map null; } // ----- 按钮2执行深度估计推理 ----- private void button2_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(image_path)) { MessageBox.Show(请先选择图片); return; } button2.Enabled false; pictureBox2.Image null; textBox1.Text ; Application.DoEvents(); // 读取原始图像BGR image new Mat(image_path); int originalWidth image.Cols; int originalHeight image.Rows; // ------------------ 预处理 ------------------ // 1. 缩放至模型输入尺寸 512x512 Mat resized new Mat(); Cv2.Resize(image, resized, new OpenCvSharp.Size(inpWidth, inpHeight)); // 2. 转换为浮点型并归一化到 [0,1] resized.ConvertTo(resized, MatType.CV_32FC3, 1.0 / 255.0); // 3. 分离 BGR 通道并按 RGB 顺序填充模型预期 RGB Mat[] channels Cv2.Split(resized); // channels[0]B, [1]G, [2]R int channelSize inpHeight * inpWidth; float[] inputData new float[3 * channelSize]; // 将 B,G,R 重新排列为 R,G,B for (int c 0; c 3; c) { float[] channelData new float[channelSize]; System.Runtime.InteropServices.Marshal.Copy(channels[c].Data, channelData, 0, channelSize); int targetIndex (c 0) ? 2 : (c 2) ? 0 : 1; // B-2, G-1, R-0 Array.Copy(channelData, 0, inputData, targetIndex * channelSize, channelSize); } // 4. 创建输入张量 input_tensor new DenseTensorfloat(inputData, new[] { 1, 3, inpHeight, inpWidth }); input_container.Clear(); input_container.Add(NamedOnnxValue.CreateFromTensor(input, input_tensor)); // ------------------ 推理 ------------------ dt1 DateTime.Now; result_infer onnx_session.Run(input_container); dt2 DateTime.Now; // 获取输出 var output result_infer.First(x x.Name output).AsTensorfloat(); var dimensions output.Dimensions.ToArray(); int outH dimensions.Length 2 ? dimensions[dimensions.Length - 2] : inpHeight; int outW dimensions.Length 1 ? dimensions[dimensions.Length - 1] : inpWidth; float[] depthFloat output.ToArray(); // 创建单通道深度 Mat (CV_32FC1) Mat depthRaw new Mat(outH, outW, MatType.CV_32FC1); System.Runtime.InteropServices.Marshal.Copy(depthFloat, 0, depthRaw.Data, depthFloat.Length); // ------------------ 后处理 ------------------ // 1. 双线性插值至原始尺寸 Mat depthResized new Mat(); Cv2.Resize(depthRaw, depthResized, new OpenCvSharp.Size(originalWidth, originalHeight), interpolation: InterpolationFlags.Linear); // 2. 反转深度使近处物体更亮 if (inverse_depth) { Cv2.Subtract(1.0, depthResized, depthResized); } // 3. 归一化深度到 [0,1] 用于彩色映射 double minVal, maxVal; Cv2.MinMaxLoc(depthResized, out minVal, out maxVal); float range (float)(maxVal - minVal); if (range 1e-6) range 1e-6f; Mat depthNorm new Mat(); depthResized.ConvertTo(depthNorm, MatType.CV_32FC1, 1.0 / range, -minVal / range); Cv2.Min(depthNorm, 1.0, depthNorm); Cv2.Max(depthNorm, 0.0, depthNorm); // 4. 转换为 8-bit 灰度图 Mat depthGray new Mat(); depthNorm.ConvertTo(depthGray, MatType.CV_8UC1, 255.0); // 5. 应用热力图Inferno 风格 depth_color_map new Mat(); Cv2.ApplyColorMap(depthGray, depth_color_map, ColormapTypes.Inferno); // 显示结果 pictureBox2.Image new Bitmap(depth_color_map.ToMemoryStream()); textBox1.Text $推理耗时: {(dt2 - dt1).TotalMilliseconds:F2} ms\n深度范围: [{minVal:F3}, {maxVal:F3}]; button2.Enabled true; } // ----- 按钮3保存深度彩色图 ----- private void button3_Click(object sender, EventArgs e) { if (depth_color_map null || depth_color_map.Empty()) { MessageBox.Show(请先执行深度估计); return; } SaveFileDialog sdf new SaveFileDialog(); sdf.Title 保存深度彩色图; sdf.Filter PNG图片 (*.png)|*.png|JPEG图片 (*.jpg)|*.jpg|BMP图片 (*.bmp)|*.bmp; sdf.FilterIndex 1; if (sdf.ShowDialog() DialogResult.OK) { Cv2.ImWrite(sdf.FileName, depth_color_map); MessageBox.Show($保存成功: {sdf.FileName}); } } // ----- 窗体加载初始化 ONNX 模型 ----- private void Form1_Load(object sender, EventArgs e) { startupPath Application.StartupPath; // 深度估计模型路径请根据实际位置修改 model_path System.IO.Path.Combine(startupPath, model, depth-model-vitb16_384.onnx); if (!System.IO.File.Exists(model_path)) { MessageBox.Show($模型文件不存在: {model_path}\n请将模型放置于 {startupPath}\\model\\ 目录下); return; } options new SessionOptions(); options.LogSeverityLevel OrtLoggingLevel.ORT_LOGGING_LEVEL_INFO; options.AppendExecutionProvider_CPU(0); // 若需 CUDA可取消注释 // options.AppendExecutionProvider_CUDA(0); onnx_session new InferenceSession(model_path, options); input_container new ListNamedOnnxValue(); // 可选默认测试图片 string testImg System.IO.Path.Combine(startupPath, test_img, 0.jpg); if (System.IO.File.Exists(testImg)) { image_path testImg; pictureBox1.Image new Bitmap(image_path); image new Mat(image_path); } } // ----- 双击图片放大保留原功能----- private void pictureBox1_DoubleClick(object sender, EventArgs e) { Common.ShowNormalImg(pictureBox1.Image); } private void pictureBox2_DoubleClick(object sender, EventArgs e) { Common.ShowNormalImg(pictureBox2.Image); } } }引入地址