当前位置: 首页 > article >正文

C# OnnxRuntime 部署 DAViD 表面法线估计

目录效果模型信息项目代码下载效果模型信息Model Properties-------------------------metadata{}---------------------------------------------------------------Inputs-------------------------nameinputtensorFloat[-1, 3, 512, 512]---------------------------------------------------------------Outputs-------------------------nameoutputtensorFloat[-1, 3, 512, 512]---------------------------------------------------------------项目代码using Microsoft.ML.OnnxRuntime;using Microsoft.ML.OnnxRuntime.Tensors;using OpenCvSharp;using System;using System.Collections.Generic;using System.Drawing;using System.Drawing.Imaging;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; // 原始图像BGRMat normal_color_map; // 生成的法线彩色图SessionOptions options;InferenceSession onnx_session;Tensorfloat input_tensor;ListNamedOnnxValue input_container;IDisposableReadOnlyCollectionDisposableNamedOnnxValue result_infer;int inpHeight 512, inpWidth 512;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;normal_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();// 读取原始图像BGRimage new Mat(image_path);int originalWidth image.Cols;int originalHeight image.Rows;// ------------------ 预处理 ------------------// 1. 缩放至模型输入尺寸 512x512Mat 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 顺序填充模型预期 RGBMat[] channels Cv2.Split(resized); // channels[0]B, [1]G, [2]Rint channelSize inpHeight * inpWidth;float[] inputData new float[3 * channelSize];// 将 B,G,R 重新排列为 R,G,Bfor (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-0Array.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 outChannels dimensions[1]; // 应为 3int outH dimensions[2];int outW dimensions[3];float[] normalFloat output.ToArray();// 创建三通道法线 Mat (CV_32FC3)形状 H×W×3Mat normalRaw new Mat(outH, outW, MatType.CV_32FC3);// 注意输出张量布局为 [N,C,H,W]需要转换为 H,W,C 存储int planeSize outH * outW;for (int c 0; c outChannels; c){float[] channelData new float[planeSize];Array.Copy(normalFloat, c * planeSize, channelData, 0, planeSize);// 将每个通道的数据填充到 Mat 的对应通道Mat channelMat new Mat(outH, outW, MatType.CV_32FC1);System.Runtime.InteropServices.Marshal.Copy(channelData, 0, channelMat.Data, planeSize);// 将单通道合并到 normalRawMat[] destChannels Cv2.Split(normalRaw);channelMat.CopyTo(destChannels[c]);Cv2.Merge(destChannels, normalRaw);}// ------------------ 后处理 ------------------// 1. 双线性插值恢复原始尺寸Mat normalResized new Mat();Cv2.Resize(normalRaw, normalResized, new OpenCvSharp.Size(originalWidth, originalHeight), interpolation: InterpolationFlags.Linear);// 2. 归一化法线向量确保每个像素的向量长度为1防止模型输出未严格归一化Mat[] normChannels Cv2.Split(normalResized);Mat normSq new Mat();Cv2.Pow(normChannels[0], 2, normSq);Mat tmp new Mat();Cv2.Pow(normChannels[1], 2, tmp);Cv2.Add(normSq, tmp, normSq);Cv2.Pow(normChannels[2], 2, tmp);Cv2.Add(normSq, tmp, normSq);Mat norm new Mat();Cv2.Sqrt(normSq, norm);norm 1e-8; // 避免除零for (int i 0; i 3; i){Cv2.Divide(normChannels[i], norm, normChannels[i]);}Mat normalizedNormal new Mat();Cv2.Merge(normChannels, normalizedNormal);// 3. 将法线从 [-1,1] 映射到 [0,255] 并转为 8UC3 用于显示Mat normalDisplay new Mat();normalizedNormal.ConvertTo(normalDisplay, MatType.CV_32FC3, 127.5, 127.5); // 0.5*255 127.5, 映射后值域[0,255]normalDisplay.ConvertTo(normalDisplay, MatType.CV_8UC3);// 注意OpenCV 默认 BGR 顺序而法线 RGB 直接显示可能会颜色偏差若需要保持 RGB 可交换 R 和 B// 这里为了视觉效果交换 R 和 B 通道使显示更自然法线常见可视化中 R 对应 XG 对应 YB 对应 ZMat[] displayChannels Cv2.Split(normalDisplay);// 交换 R 和 BMat temp displayChannels[0].Clone();displayChannels[0] displayChannels[2];displayChannels[2] temp;Cv2.Merge(displayChannels, normalDisplay);normal_color_map normalDisplay.Clone();// 显示结果pictureBox2.Image new Bitmap(normal_color_map.ToMemoryStream());textBox1.Text $推理耗时: {(dt2 - dt1).TotalMilliseconds:F2} ms;button2.Enabled true;}// ----- 按钮3保存法线彩色图 -----private void button3_Click(object sender, EventArgs e){if (normal_color_map null || normal_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, normal_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, normal-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);}}// ----- 双击图片放大保留原功能假设存在 Common 类-----private void pictureBox1_DoubleClick(object sender, EventArgs e){Common.ShowNormalImg(pictureBox1.Image);}private void pictureBox2_DoubleClick(object sender, EventArgs e){Common.ShowNormalImg(pictureBox2.Image);}}}using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; 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 normal_color_map; // 生成的法线彩色图 SessionOptions options; InferenceSession onnx_session; Tensorfloat input_tensor; ListNamedOnnxValue input_container; IDisposableReadOnlyCollectionDisposableNamedOnnxValue result_infer; int inpHeight 512, inpWidth 512; 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; normal_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 outChannels dimensions[1]; // 应为 3 int outH dimensions[2]; int outW dimensions[3]; float[] normalFloat output.ToArray(); // 创建三通道法线 Mat (CV_32FC3)形状 H×W×3 Mat normalRaw new Mat(outH, outW, MatType.CV_32FC3); // 注意输出张量布局为 [N,C,H,W]需要转换为 H,W,C 存储 int planeSize outH * outW; for (int c 0; c outChannels; c) { float[] channelData new float[planeSize]; Array.Copy(normalFloat, c * planeSize, channelData, 0, planeSize); // 将每个通道的数据填充到 Mat 的对应通道 Mat channelMat new Mat(outH, outW, MatType.CV_32FC1); System.Runtime.InteropServices.Marshal.Copy(channelData, 0, channelMat.Data, planeSize); // 将单通道合并到 normalRaw Mat[] destChannels Cv2.Split(normalRaw); channelMat.CopyTo(destChannels[c]); Cv2.Merge(destChannels, normalRaw); } // ------------------ 后处理 ------------------ // 1. 双线性插值恢复原始尺寸 Mat normalResized new Mat(); Cv2.Resize(normalRaw, normalResized, new OpenCvSharp.Size(originalWidth, originalHeight), interpolation: InterpolationFlags.Linear); // 2. 归一化法线向量确保每个像素的向量长度为1防止模型输出未严格归一化 Mat[] normChannels Cv2.Split(normalResized); Mat normSq new Mat(); Cv2.Pow(normChannels[0], 2, normSq); Mat tmp new Mat(); Cv2.Pow(normChannels[1], 2, tmp); Cv2.Add(normSq, tmp, normSq); Cv2.Pow(normChannels[2], 2, tmp); Cv2.Add(normSq, tmp, normSq); Mat norm new Mat(); Cv2.Sqrt(normSq, norm); norm 1e-8; // 避免除零 for (int i 0; i 3; i) { Cv2.Divide(normChannels[i], norm, normChannels[i]); } Mat normalizedNormal new Mat(); Cv2.Merge(normChannels, normalizedNormal); // 3. 将法线从 [-1,1] 映射到 [0,255] 并转为 8UC3 用于显示 Mat normalDisplay new Mat(); normalizedNormal.ConvertTo(normalDisplay, MatType.CV_32FC3, 127.5, 127.5); // 0.5*255 127.5, 映射后值域[0,255] normalDisplay.ConvertTo(normalDisplay, MatType.CV_8UC3); // 注意OpenCV 默认 BGR 顺序而法线 RGB 直接显示可能会颜色偏差若需要保持 RGB 可交换 R 和 B // 这里为了视觉效果交换 R 和 B 通道使显示更自然法线常见可视化中 R 对应 XG 对应 YB 对应 Z Mat[] displayChannels Cv2.Split(normalDisplay); // 交换 R 和 B Mat temp displayChannels[0].Clone(); displayChannels[0] displayChannels[2]; displayChannels[2] temp; Cv2.Merge(displayChannels, normalDisplay); normal_color_map normalDisplay.Clone(); // 显示结果 pictureBox2.Image new Bitmap(normal_color_map.ToMemoryStream()); textBox1.Text $推理耗时: {(dt2 - dt1).TotalMilliseconds:F2} ms; button2.Enabled true; } // ----- 按钮3保存法线彩色图 ----- private void button3_Click(object sender, EventArgs e) { if (normal_color_map null || normal_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, normal_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, normal-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); } } // ----- 双击图片放大保留原功能假设存在 Common 类----- private void pictureBox1_DoubleClick(object sender, EventArgs e) { Common.ShowNormalImg(pictureBox1.Image); } private void pictureBox2_DoubleClick(object sender, EventArgs e) { Common.ShowNormalImg(pictureBox2.Image); } } }下载源码下载

相关文章:

C# OnnxRuntime 部署 DAViD 表面法线估计

目录 效果 模型信息 项目 代码 下载 效果 模型信息 Model Properties ------------------------- metadata:{} --------------------------------------------------------------- Inputs ------------------------- name:input tensor&#xff1…...

Kubernetes 生产环境调试安全最佳实践:2026 年完整指南

Kubernetes 生产环境调试安全最佳实践:2026 年完整指南 摘要:在生产环境中调试 Kubernetes 集群是每个 DevOps 工程师和 SRE 的日常工作。然而,传统的调试方法往往依赖宽泛的集群管理员权限、共享跳板机或长期有效的 SSH 密钥,这些…...

Halcon轮廓分割进阶:segment_contours_xld的‘两步逼近’算法原理与参数调优实战

Halcon轮廓分割进阶:segment_contours_xld的‘两步逼近’算法原理与参数调优实战 在工业视觉检测领域,轮廓分割的精度直接影响着后续几何特征提取的准确性。Halcon作为机器视觉领域的标杆软件,其segment_contours_xld算子通过独特的"两步…...

告别商业EDA?在Ubuntu 22.04上配置开源EDA工具链:Yosys + GTKWave + iverilog

开源EDA工具链实战:在Ubuntu 22.04上构建YosysGTKWaveiverilog全流程环境 当我在大学实验室第一次接触FPGA开发时,商业EDA软件动辄数十万的授权费用让我震惊。直到发现开源EDA工具链,才意识到原来芯片设计可以如此"平民化"。本文将…...

[嵌入式系统-261]:设备管理中的几个核心概念:设备名称、设备文件描述符、主设备号(主设备号与次设备号)以及他们之间的关系

在 Linux 操作系统中,设备管理遵循“一切皆文件”的设计哲学。为了让你清晰地理解这些核心概念及其关系,我们可以把设备管理看作一个“查快递”的过程。以下是设备名称、设备文件描述符、主设备号和次设备号的详细解析及它们之间的协作关系。1. 核心概念…...

保姆级教程:手把手教你用QFIL救活高通9008端口变砖的手机(附常见错误日志分析)

高通9008端口救砖全指南:从QFIL操作到日志分析实战 当你的手机因刷机失败、系统崩溃彻底变砖,连开机画面都消失时,高通9008端口往往是最后的救命稻草。作为芯片级修复模式,它绕过了所有系统层限制,允许直接与处理器通信…...

【网络基础科普】交换机 MAC 地址全解析:查询方法、System MAC 与 Bridge MAC 的区别,以及“为什么只差 1”

一、背景:为什么要搞懂交换机 MAC? 在很多网络运维场景中,查询交换机 MAC 地址是刚性要求: 从资产台账、合规审计,到故障排查与网络设计,MAC 地址都是基础且关键的数据。 本文从真实运维背景出发&#xf…...

《SAP FICO系统配置从入门到精通共40篇》039、FICO配置传输管理(CTS)与版本控制:那些年我们追过的传输请求

039、FICO配置传输管理(CTS)与版本控制:那些年我们追过的传输请求一、凌晨三点的紧急电话 上个月某个深夜,手机突然狂震。客户生产系统的一个关键成本中心会计凭证突然报错,追溯后发现是某个成本要素类别配置被意外覆盖…...

2026最稳代练创业项目:三角洲护航系统——全端部署+智能匹配,破解获客与信任难题

一、项目核心价值:低成本搭建,100%利润掌控 传统代练模式依赖第三方平台抽成(20%-50%),利润被严重压缩。而三角洲护航系统基于UniAppThinkPHP6架构,支持微信小程序、H5、APP、PC端多端同步,创业…...

解锁论文“黑科技”:书匠策AI带你玩转期刊论文全流程

在学术的江湖里,期刊论文就像是一张通往学术殿堂的“入场券”,每一位学者都渴望凭借高质量的论文在学术舞台上崭露头角。然而,论文写作的过程却充满了挑战,选题迷茫、文献整理繁琐、结构混乱、格式错误……这些问题常常让学者们焦…...

告别手动布线烦恼:用Allegro快速布局STM32核心板的5个高效技巧

告别手动布线烦恼:用Allegro快速布局STM32核心板的5个高效技巧 在嵌入式硬件开发中,PCB布局往往是项目进度中最耗时的环节之一。特别是对于STM32这类功能丰富的主控芯片,如何高效地完成核心板布局,同时保证信号完整性和可布线性&a…...

别光会explain()了!Spark 3.0+ 中这几个隐藏的执行计划模式更实用

解锁Spark执行计划的隐藏模式:超越explain()的高级调试技巧 当你在Spark作业遇到性能瓶颈时,是否还在反复查看基础explain()输出却找不到头绪?作为数据工程师,我们常常陷入这样的困境:明明知道执行计划很重要&#xff…...

GD32F103串口调试:从printf重定向到中断收发,一个工程搞定所有(附完整代码)

GD32F103串口工程实战:从printf重定向到中断收发的完整解决方案 刚拿到GD32F103开发板时,串口调试往往是第一个需要攻克的难题。如何快速搭建一个稳定可靠的串口通信环境?本文将带你从零开始构建一个完整的串口工程,涵盖printf重定…...

z z z z z z z z z z z z z z z

z z z z z z z z z z z z...

q q q q q q q q q q q q q q q q q q q

q q q q q q q q q...

w w w w w w w w w w w w w

w w w w w w w w w w w...

010、展望:架构演化的逻辑与未来——效率、智能与硬件协同设计之路

昨天深夜调一个BERT模型部署,显存又爆了。盯着监控面板上那条陡峭的曲线,我忽然想起三年前同样的场景——那时候我们还在争论要不要上Transformer。从BERT到GPT,再到最近冒出来的Mamba,这条演化路径背后到底藏着什么逻辑?今天不聊具体代码,咱们聊聊这条路上的风景和还没修…...

JavaScript中严格模式use-strict对引擎解析的辅助

严格模式不是语法糖,而是启用更严谨的解析执行模式,提前报错、明确作用域、规范this绑定、禁止危险操作,为引擎优化提供确定性前提。严格模式("use strict")不是语法糖,而是告诉 JavaScript 引擎…...

CSS如何优化移动端响应式断点设置_利用移动优先策略编写代码

移动端断点不能照搬桌面尺寸,因现代设备的视口缩放与物理像素脱钩;应基于内容溢出临界点,用 min-width 递增式增强,配合正确 viewport 设置(widthdevice-width),避免历史固定值和 max-width 覆盖…...

从逻辑漏洞到清晰闭环:用流程图思维提升你的PRD文档质量(附避坑清单)

从逻辑漏洞到清晰闭环:用流程图思维提升你的PRD文档质量(附避坑清单) 在互联网产品开发中,PRD文档的质量往往决定了整个团队的协作效率。我们常遇到这样的场景:开发过程中突然发现某个关键流程存在逻辑断点&#xff0c…...

CSS如何实现列表项序号自定义_利用--before与content实现

当list-style-type无法满足自定义序号需求时,应改用::beforecontent配合CSS计数器;需设置counter-reset、counter-increment,并在content中引用counter(),支持前缀、图标、嵌套及无障碍阅读。list-style-type 不能满足自定义序号时…...

别再只用view了!微信小程序text组件的5个隐藏用法,让你的页面排版更专业

微信小程序text组件的5个高阶玩法:从排版细节到交互设计 在微信小程序的开发过程中,text组件往往被视为最简单的元素之一——仅仅用于展示静态文本。但如果你也这样认为,那么你可能错过了这个基础组件75%的实用功能。今天,我们将突…...

从STM32转战航顺HK32F030MF4P6:定时器配置的那些“坑”与避雷指南

从STM32转战航顺HK32F030MF4P6:定时器配置的那些“坑”与避雷指南 作为一名长期使用STM32的开发者,初次接触航顺HK32系列时,往往会带着STM32的思维惯性去配置外设。这种经验复用本应是优势,但在定时器这类对细节敏感的外设上&…...

老队员的建议:怨天不由人,收获在自己

简 介: 【】一位往届选手针对智能车竞赛自制车模争议提出建议:1)反对因自制车模被超越而要求改规则的行为,认为应通过提升设计水平公平竞争;2)强调比赛"立足培养"的宗旨应兼顾基础薄弱学生&#…...

【Dify 2026插件开发权威指南】:零基础到生产级自定义插件的7大核心实践与避坑清单

第一章:Dify 2026插件生态全景与开发范式演进Dify 2026标志着插件架构从“能力扩展”迈向“智能协同”的关键跃迁。其插件生态不再局限于API代理或简单工具封装,而是以统一的语义契约(Semantic Contract)为基础,支持跨…...

通用ADC芯片测试:其TSSOP16、QFN16封装与德诺嘉电子芯片测试座角色应用

在车规级电子(如车载传感器、电池管理系统)与医疗电子(如便携式诊断设备、生命体征监测仪器)领域,通用ADC(模数转换)芯片作为模拟信号与数字信号的“桥梁”,其性能直接决定设备的数据…...

iFakeLocation:iOS设备虚拟定位的终极指南,免费跨平台解决方案

iFakeLocation:iOS设备虚拟定位的终极指南,免费跨平台解决方案 【免费下载链接】iFakeLocation Simulate locations on iOS devices on Windows, Mac and Ubuntu. 项目地址: https://gitcode.com/gh_mirrors/if/iFakeLocation 想要在iOS设备上自由…...

STM32串口调试流程讲解

目录 一、串口调试介绍 二、XCOM以及驱动程序安装 1.XCOM图 2.CH340图 三、硬件连接 四、代码讲解 五、调试结果 六、资料获取 项目分享 一、串口调试介绍 调试是指在嵌入式开发过程中,通过一定的手段和方法,对硬件与软件进行测试、验证与问题排…...

FutureRestore-GUI 2025版:图形化iOS降级终极解决方案

FutureRestore-GUI 2025版:图形化iOS降级终极解决方案 【免费下载链接】FutureRestore-GUI A modern GUI for FutureRestore, with added features to make the process easier. 项目地址: https://gitcode.com/gh_mirrors/fu/FutureRestore-GUI FutureResto…...

DolphinScheduler 3.x 集成 DataX 保姆级教程:从环境变量到HDFS权限,一次搞定所有坑

DolphinScheduler 3.x 与 DataX 深度集成实战:权限控制与性能调优全解析 在数据工程领域,ETL 流程的稳定性和效率直接影响着数据仓库的质量和时效性。DolphinScheduler 作为一款开源的分布式工作流调度系统,与阿里巴巴开源的 DataX 数据同步工…...