news 2026/9/27 23:11:12

C# WinForm 部署 YOLO26-OBB 旋转框检测 ONNX 模型实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C# WinForm 部署 YOLO26-OBB 旋转框检测 ONNX 模型实战

简介:面向C#开发者的YOLO26-OBB旋转框检测部署演示包,基于WinForms框架实现,适合需要在桌面应用中集成定向目标检测能力的开发者,也可作为目标检测入门的学习范例。项目将官方yolo26n-obb.pt导出的ONNX模型与OpenCvSharp图像处理管线结合,支持任意角度旋转框的识别输出,全程CPU推理,无需CUDA与cuDNN等GPU环境,搭配onnxruntime 1.22.1与.NET Framework 4.8.0即能运行,已在VS2019下完成测试,适合已有基础WinForms经验的中级开发者直接上手参考。压缩包共92个文件、约70MB,其中包含10个C#源码文件、30个运行库DLL、1个核心ONNX模型,另有工程配置、使用说明、缓存与调试日志等辅助文件,目录结构清晰,加载后可立即编译调试,并可按需替换自训练模型。若自行训练了YOLO26-OBB模型,仅需导出ONNX格式后替换即可复用整套检测逻辑。目前已有131人学习下载,适合作为旋转框识别技术入口或工业质检、遥感影像、自动驾驶等场景的原型验证参考。

1. 为什么把 C# WinForm 部署 YOLO26-OBB 旋转框检测的 ONNX 模型放在一起

做视觉上位机的朋友应该都遇到过这个场景:传送带上的工件角度千奇百怪,水平检测框把两个挨得近的目标框成一个矩形,NMS 一通乱删,最后误检漏检堆了一屏。我现在的做法是在 C# WinForm 工程里直接部署 yolo26-obb 旋转框检测的 ONNX 模型,用 OnnxRuntime 加载,输出带角度的旋转矩形,画框、统计结果、联动 PLC 一次到位。这套方案演示源码的核心不复杂:模型是 OBB 权重转的 ONNX,C# 端只管预处理、推理、旋转框后处理和画框四件事。适合两类人:一类是要在工控机上快速做原型验证的,另一类是想把手头水平框检测改成旋转框、又不知道角度怎么对齐的。不适合追求极致帧率的人,那种场景应该上 TensorRT 和 C++,而不是 WinForm。

2. 旋转框检测和水平框差距在哪:从角度定义到 YOLO26-OBB 的输出结构

2.1 水平框为什么在密排场景下先输一半

水平框检测的输出是 (x, y, w, h),没有角度。目标一旦倾斜,这个框里会混进大量背景,框本身也不再是目标的最小外接矩形。两个倾斜的目标挨得越近,水平框之间的重叠区域越大,IoU 虚高,NMS 抑制时后一个目标直接被删掉。这不是检测器的问题,是表达方式的问题。

在航拍、遥感、工业近景这些场景里,目标方向几乎随机,尤其是 PCB 板上倾斜的芯片、任意角度的工件、货架上的料箱。用水平框跑,漏检率很难压下去,而且你也没法告诉机械手这个工件到底转了多少度。旋转框检测解决的就是“框住目标 + 告诉角度”这两件事,输出变成 (cx, cy, w, h, angle),画出来是一个带角度的矩形,贴合目标轮廓,漏检和误检都会明显下降。

YOLO26-OBB 是 YOLO 系列里带 OBB 头的版本,它和 YOLOv8-OBB、YOLO11-OBB 在部署侧呈现的是同一套输出约定,所以你不必纠结它内部主干到底改了多少层,部署时只需要盯住输出张量的形状、通道顺序和角度约定这三件事。

2.2 YOLO26-OBB 输出了什么:四个坐标加一个角度

OBB 检测头的输出维度和普通 YOLO 检测头的区别在于多了一个角度通道。以常见的类别数 nc 为例,输出通道 C = 4 + nc + 1。4 是中心点和宽高,nc 是类别概率,最后 1 是角度。注意 YOLO 系列较新的版本没有 objectness 置信度分支,置信度直接用类别概率最大值代替,所以 C 里不要再算一个额外的 obj 通道。

输出张量在 ONNX 里常见两种排布:一种是 [1, N, C],N 是三层特征图上的候选框总数,每个候选框是一行,直接按行读;另一种是 [1, C, N],需要转置成 [N, C] 再逐行处理。以输入 640x640 为例,常见算例是 80x80、40x40、20x20 三层网格,候选框总数大概是 8400 这个量级,具体数字以你导出的模型为准,不要拿别人的结论硬套。

有的导出脚本会把角度放在第一个位置或者紧挨宽高后面,这个顺序没有任何标准,唯一可靠的办法是先用 Netron 打开 onnx 看最后的卷积权重结构,或者在同一张图上对比 PyTorch 推理结果把角度的位置试出来。这也是后面调试最容易翻车的地方。

2.3 角度定义的两种写法,部署前必须统一

角度是最容易出问题的部分,比坐标回归还容易出问题。常见角度定义有几种,部署时必须统一到同一种约定。

一种是长边定义法,角度范围在 [-90, 0),用 OpenCV 的 RotatedRect 和 DOTA 数据集的四点多边形转换过来时常用这种写法。另一种是 YOLO-OBB 系列训练时把角度归一化到 [0, 1],映射实际 0 到 90 度,推理时需要把网络输出的原始数值乘回 90 度。第三种是直接输出弧度,范围可能是 [-pi/2, pi/2) 或者 [0, pi)。

我在 C# 端习惯把角度还原写成一个单独的配置项,不写死在解码函数里。比如代码里定义一个AngleScale常量,模型训练时是归一化占比就乘 90f,是弧度就乘 MathF.PI / 180f,方向不对就在前面加负号。先跑通流程,再对着标注图校准方向,比一开始就追求公式完全正确靠谱得多。

提示:拿到任何 OBB 模型,第一件事不是写代码,是找一张带旋转框标注的验证图,把模型输出的角度打印出来和标注比对,确认乘法和符号。这一步能省掉后面至少半天的排查时间。

3. 把 YOLO26-OBB 训练权重导出成 ONNX:转换脚本与参数验证

3.1 导出命令与老生常谈的 opset、动态轴

PyTorch 转 ONNX 现在已经有很成熟的套路,关键是几个参数别选错。以 UltraLytics 训练出的 best.pt 为例,导出脚本长这样:

from ultralytics import YOLO model = YOLO("runs/obb/train/weights/best.pt") model.export( format="onnx", opset=17, imgsz=640, dynamic=False, simplify=True )

opset 选 17 主要考虑 OnnxRuntime 的兼容性,OnnxRuntime 1.14 以上对 opset 17 支持得很稳。imgsz 固定 640 是我推荐的第一个版本,因为固定输入尺寸后 C# 端的预处理可以写死,后处理的维度判断也简单。dynamic=False 时 ONNX 输入是固定 shape,OnnxRuntime 加载时不会报动态维度相关的错。

如果你想在运行时灵活切换分辨率,可以改成 dynamic=True,但 C# 端每次推理都要重新确认输入输出维度,复杂度会明显上升。我的习惯是先固定 640 把整条链路跑通,后面需要提速再开动态轴做多档分辨率。simplify=True 会调用 onnxsim 做常量折叠和算子融合,能去掉一批无用节点,在 WinForm 部署场景里值得开。

3.2 导出后用 Netron 和一段 Python 确认输出通道含义

导出之后别急着写 C#,先用 onnx 库打印输入输出信息,这一步能确认很多东西:

import onnx m = onnx.load("best_obb.onnx") print("=== INPUT ===") for inp in m.graph.input: print(inp.name, [d.dim_value or "dynamic" for d in inp.type.tensor_type.shape.dim]) print("=== OUTPUT ===") for out in m.graph.output: print(out.name, [d.dim_value or "dynamic" for d in out.type.tensor_type.shape.dim])

这段代码不依赖显卡,跑在 CPU 上就行。输出里如果某个维度显示 0,是因为 dim_value 没有显式赋值,表示动态维度,C# 端要拿运行时 shape 来推导。如果输出是 [1, 20, 8400],说明你的模型是 15 类 DOTA 风格,20 = 4 + 15 + 1,并且输出是 CHW 排布,C# 端需要转置。如果打印出来是 [1, 8400, 20],那直接逐行读就行。

还需要确认角度通道的确切位置。常见两种:一是角度放在坐标后面的第 4 个位置,二是放在整个通道的最后一位。最准的办法是写一段小脚本,读一张测试图调用 onnxruntime 推理,把每一行的最后一个通道和倒数第二个通道打印出来,看哪一段数值和已知角度对得上。这个动作虽然多花十分钟,但比在 C# 端反复试错快得多。

3.3 模型压缩选 FP16 还是 INT8:角度回归受不了 int8

模型在 CPU 上跑得慢,很多人第一时间想到量化。旋转框检测模型对量化比普通水平框更敏感,因为角度是连续回归量,量化误差会直接反映在角度漂移上。

我做过一组对比,同一模型 FP32 和 INT8 的角度误差平均在 1 到 3 度,密集小目标场景下更高。角度偏 2 度,矩形顶点在长边方向可能偏出好几个像素,后续做抓取定位会出大问题。在 GPU 可用时优先转 FP16,精度损失小,速度提升明显;只有 CPU 的场景再考虑 INT8,并且量化后必须跑一遍验证集统计平均角度误差。onnx 转 ncnn 那个路线更适合带 NPU 的边缘盒子,Windows 桌面端没必要绕远路。

4. 在 WinForm 里跑通 ONNX 推理:从加载模型到画旋转框

4.1 NuGet 引用与 SessionOption 配置

C# 端跑 ONNX 首选 OnnxRuntime 的 NuGet 包,直接引用Microsoft.ML.OnnxRuntime就够了。版本选择有个血泪经验:包版本和运行时原生 DLL 必须一致,不同大版本混用会在运行时报奇怪的加载错误。模型加载代码我一般这样写:

using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; InferenceSession _session; public void LoadModel(string modelPath, bool useGpu) { var options = new SessionOptions(); options.GraphOptimizationLevel = GraphOptimizationLevel.ORT_ENABLE_ALL; options.IntraOpNumThreads = Environment.ProcessorCount; if (useGpu) { try { options.AppendExecutionProvider_CUDA(0); } catch (Exception ex) { // CUDA 执行提供程序注册失败,回退 CPU,别直接崩 System.Diagnostics.Debug.WriteLine(ex.Message); } } _session = new InferenceSession(modelPath, options); // 打印输入输出元数据,方便核对维度 foreach (var meta in _session.InputMetadata) Console.WriteLine($"input: {meta.Key}, {string.Join(",", meta.Value.Dimensions)}"); }

GraphOptimizationLevel 开 ORT_ENABLE_ALL 能触发 OnnxRuntime 的图优化,对 CPU 和 GPU 都有收益。IntraOpNumThreads 设为 CPU 核心数,多核机器上能明显压低单帧延迟。GPU 分支必须包在 try/catch 里,工控机上没装 CUDA 组件时不至于让整个程序起不来。

4.2 letterbox 预处理与坐标还原

预处理按 YOLO 系列的惯例做 letterbox,也就是等比缩放后灰边填充。这一步的核心是记录缩放比和填充偏移,因为后处理把坐标还原到原图时要用这两个值:

static float[] Preprocess(Bitmap src, int dstSize, out float ratio, out int padX, out int padY) { ratio = Math.Min((float)dstSize / src.Width, (float)dstSize / src.Height); int newW = (int)Math.Round(src.Width * ratio); int newH = (int)Math.Round(src.Height * ratio); padX = (dstSize - newW) / 2; padY = (dstSize - newH) / 2; using var resized = new Bitmap(newW, newH); using (var g = Graphics.FromImage(resized)) { g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear; g.DrawImage(src, 0, 0, newW, newH); } var data = new float[3 * dstSize * dstSize]; var bmpData = resized.LockBits(new Rectangle(0, 0, newW, newH), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); unsafe { byte* p = (byte*)bmpData.Scan0; for (int y = 0; y < newH; y++) { byte* row = p + y * bmpData.Stride; for (int x = 0; x < newW; x++) { int dx = x + padX, dy = y + padY; float b = row[x * 3] / 255f; float g = row[x * 3 + 1] / 255f; float r = row[x * 3 + 2] / 255f; data[0 * dstSize * dstSize + dy * dstSize + dx] = r; data[1 * dstSize * dstSize + dy * dstSize + dx] = g; data[2 * dstSize * dstSize + dy * dstSize + dx] = b; } } } resized.UnlockBits(bmpData); return data; }

这段代码里 LockBits + 指针操作比逐像素 GetPixel 快一个数量级,配合 unsafe 需要在项目属性里打开允许不安全代码。如果不想开 unsafe,也可以用 Marshal.Copy 把整行拷到 byte[] 再访问,速度差不多。填充区域保持 0,也就是归一化后的纯黑,符合训练时的填充习惯。

4.3 输出解析与旋转框解码

推理调用本身很短,难的是把输出张量按正确的维度方向解开。常见错误是默认输出是 [1, N, C],结果模型导出来是 [1, C, N],一索引就全乱。我一般这样处理:

public List<RotatedBox> Detect(Bitmap bmp, float confThres) { float ratio; int padX, padY; float[] data = Preprocess(bmp, 640, out ratio, out padX, out padY); var shape = new long[] { 1L, 3L, 640L, 640L }; using var inputTensor = new DenseTensor<float>(data, shape); var feed = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor("images", inputTensor) }; using var results = _session.Run(feed); var output = results.First().AsTensor<float>(); int d1 = (int)output.Dimensions[1]; int d2 = (int)output.Dimensions[2]; // 统一成 [N, C]:d1 大的是 N,d2 是 C int N = Math.Max(d1, d2); int C = Math.Min(d1, d2); var boxes = new List<RotatedBox>(); float angleScale = 90f; // 训练时角度归一化到 [0,1] 对应 0~90 度 for (int i = 0; i < N; i++) { float maxScore = 0; int bestCls = -1; for (int c = 4; c < C - 1; c++) { float score = d1 > d2 ? output[i * C + c] : output[c * N + i]; if (score > maxScore) { maxScore = score; bestCls = c; } } if (bestCls < 0 || maxScore < confThres) continue; float cx = d1 > d2 ? output[i * C + 0] : output[0 * N + i]; float cy = d1 > d2 ? output[i * C + 1] : output[1 * N + i]; float w = d1 > d2 ? output[i * C + 2] : output[2 * N + i]; float h = d1 > d2 ? output[i * C + 3] : output[3 * N + i]; float ang = d1 > d2 ? output[i * C + (C - 1)] : output[(C - 1) * N + i]; // 还原到原图坐标 cx = (cx - padX) / ratio; cy = (cy - padY) / ratio; w = w / ratio; h = h / ratio; float angleDeg = ang * angleScale; boxes.Add(new RotatedBox(cx, cy, w, h, angleDeg, maxScore, bestCls)); } return boxes; }

注意output.Dimensions的 C 和类别数 nc 不是一回事,C 是 4 + nc + 1。遍历类别分数从索引 4 到 C-2,C-1 是角度通道。如果导出的模型把角度放在第 4 个位置,这里就要改索引,这个必须按实际模型来。

4.4 旋转框 NMS:不能把普通 IoU 拿过来直接用

旋转框的目标排列紧密的时候,普通水平框 IoU 会把两个不重叠的旋转矩形算出很高的重叠率,NMS 就会把正确的目标误删。正确做法是算旋转矩形交集面积,最直接的是 Sutherland-Hodgman 多边形裁剪:

static float IntersectPolygonArea(List<PointF> a, List<PointF> b) { var clip = new List<PointF>(b); for (int i = 0; i < a.Count; i++) { var cur = a[i]; var next = a[(i + 1) % a.Count]; var edge = (cur, next); var input = clip; clip = new List<PointF>(); for (int j = 0; j < input.Count; j++) { var p = input[j]; var prev = input[(j + input.Count - 1) % input.Count]; bool pIn = IsLeft(edge, p); bool prevIn = IsLeft(edge, prev); if (pIn) clip.Add(p); if (prevIn != pIn) clip.Add(IntersectPoint(edge, prev, p)); } } return PolygonArea(clip); }

IsLeft 判断点在边的哪一侧,IntersectPoint 求线段与裁剪边的交点,PolygonArea 用高斯公式求多边形面积。这段代码不需要引入图形库,几十行就够,比用 GDI+ Region 扫像素靠谱得多。NMS 主流程按置信度降序,依次抑制交集 IoU 超过阈值的候选框即可。框数量不大时 O(n^2) 完全够用。

4.5 在 PictureBox 上画检测结果并顺手美化界面

得到旋转框四边形的四个顶点后,用 GDI+ 的 DrawPolygon 就能画出来。从 (cx, cy, w, h, angle) 计算顶点要绕一下:

public static PointF[] CalcRotatedPoints(float cx, float cy, float w, float h, float angleDeg) { float rad = angleDeg * MathF.PI / 180f; float cos = MathF.Cos(rad), sin = MathF.Sin(rad); float dx = w / 2f, dy = h / 2f; var pts = new PointF[4]; pts[0] = Rotate(-dx, -dy, cos, sin, cx, cy); pts[1] = Rotate(dx, -dy, cos, sin, cx, cy); pts[2] = Rotate(dx, dy, cos, sin, cx, cy); pts[3] = Rotate(-dx, dy, cos, sin, cx, cy); return pts; } static PointF Rotate(float x, float y, float cos, float sin, float cx, float cy) { return new PointF(cx + x * cos - y * sin, cy + x * sin + y * cos); }

绘制时用半透明填充能让旋转矩形看起来更直观,再叠加类别、置信度和角度文本。WinForm 界面美化不需要用第三方皮肤库,先把 PictureBox 的双缓冲打开避免闪烁,再把阈值调整的 TrackBar、GPU/CPU 切换的 ComboBox 放在统一的面板里,视觉上已经接近可交付的原型了。旋转框的角点如果画出来和实际目标边不贴合,优先怀疑角度符号,把 angleDeg 取负试试。

5. 部署避坑指南:旋转框模型最容易翻车的 5 个地方

5.1 框有位置但没有角度:角度定义不一致

现象:检测框位置基本准确,但角度完全不对,有的框转成 90 度,有的旋转方向反了。

原因:训练脚本的角度定义和 C# 端解码的还原方式不一致,最常见的是把长边定义法的 [-90, 0) 当成了 0 到 90 度的归一化输出,或者符号取反。

解决:找一张带标注的验证图,打印模型裸输出角度通道的数值范围。如果输出在 0 到 1 之间,大概率是归一化角度,乘以 90;如果输出在 -1.57 到 1.57 之间,那是弧度,乘 180/pi。方向反了直接加负号。调完之后再画框对比标注。

5.2 目标框整体偏移:letterbox 坐标还原写错

现象:框的中心点整体偏向右下或左上,尺寸也不太对,小目标偏移更明显。

原因:还原坐标时忘了减去 padX 和 padY,或者还原顺序错了。letterbox 是先缩放再居中填充,解码时应该先减填充偏移再除缩放比。有人先除再减,结果在填充不为 0 时全部偏移。

解决:检查还原代码,确认是(modelCoord - pad) / ratio而不是(modelCoord / ratio - pad)。调试时把 padX、padY、ratio 在窗口里显示出来,配合一张已知尺寸的目标图就能定位。

5.3 密集目标被 NMS 吞掉:用了水平框 IoU

现象:两个倾斜目标挨得近时只出一个框,置信度低的那个直接被删。

原因:后处理用了中心点宽高算 IoU,旋转矩形之间本来不重叠,水平框算出来重叠率却高达 0.6 以上,NMS 误杀。

解决:把 NMS 换成旋转框 IoU,用多边形裁剪求交集面积。这个坑在 OBB 部署里出现频率极高,几乎每个接手的人都会踩一遍,没有捷径,必须实现 rotataed IoU。

5.4 ONNX 报 InvalidArgument:动态 shape 和固定 shape 没对齐

现象:C# 端推理时报InvalidArgument,提示输入维度不匹配。

原因:导出时开了动态轴,运行时输入张量的 [1, 3, H, W] 和模型期望不一致;另一种情况是模型输入名不是默认的 "images",代码写死了输入名。

解决:加载模型后先用_session.InputMetadata.First()打印输入名和维度,不要硬编码。动态轴模型在运行时按实际 shape 创建 Tensor,固定轴模型必须严格按导出时的 imgsz 初始化。

5.5 推理崩溃 c0000005 或 CPU 占用异常:OnnxRuntime 原生库配错

现象:程序启动后第一次推理就崩溃,错误是 AccessViolationException,代码 0xC0000005;或者推理速度异常慢,CPU 单核跑满但 GPU 没生效。

原因:OnnxRuntime 的 NuGet 包版本和本机已安装的旧版本原生 DLL 冲突,或者 x64/x86 不匹配。WinForm 项目默认 AnyCPU,在 64 位机器上如果没有强制 x64,会加载到错误位数的原生库。GPU 执行提供程序的 CUDA 版本和 cuDNN 版本不匹配也会导致运行期崩溃。

解决:项目平台强制 x64,卸载所有旧 OnnxRuntime 包后重装统一版本。GPU 场景先确认本机 CUDA 和 cuDNN 版本符合当前 OnnxRuntime 的要求,否则回退 CPU 执行。c0000005 这类原生层崩溃在 C# 端很难定位,优先怀疑位数和版本冲突,别在代码逻辑里找。

6. 从演示走向工程:性能、验证和自动化校准

6.1 用真实图集跑一个小 Benchmark

演示源码跑通之后,第一步是建立性能基线。我一般会在程序里留一个隐藏的 Benchmark 窗口,加载 10 张真实产线图片到内存,重复推理 50 次,统计平均耗时、单帧 FPS、每帧平均检测框数。用 Stopwatch 包住session.Run那一行,不要包预处理,预处理在真实场景里通常是异步的。CPU 机器上如果单帧超过 80ms,优先检查 IntraOpNumThreads 是否生效,其次是输入分辨率是不是可以降到 480。GPU 机器上跑不出加速效果,先看 CUDA 执行提供程序有没有真正挂载成功。

6.2 和 PyTorch 推理对齐的校准开关

旋转框部署最怕角度方向这种低级错误流到现场,所以我会在工程里留一个校准开关:加载同一张测试图,分别用 PyTorch 脚本和 C# 工程推理,对比每个框的中心点误差、宽高误差和角度误差。中心点误差大于 0.5 像素、角度误差大于 1 度,就显示警告。这个开关平时藏起来,现场觉得结果不对时可以一键开启,不用重新编译。

我自己每次部署 OBB 模型都会强制输出一张带标注的校验图,先肉眼确认角度方向和标注一致,再交给现场。这个习惯救过我很多次,尤其是换了训练框架或改了角度定义之后。旋转框检测真正难的不是模型效果,而是把角度从训练端一路对齐到 WinForm 画框那一行代码。希望这个方向上的落地经验能帮到你少走几趟弯路。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/27 23:09:36

4592张超市秤盘水果检测数据集:VOC+YOLO双格式与YOLOv8训练实战

简介&#xff1a;面向超市智能秤盘与目标检测应用场景&#xff0c;这份数据集涵盖苹果、香蕉、黑莓、辣椒、葡萄、柠檬、树莓、番茄等14类常见水果&#xff0c;并区分带包装&#xff08;wb&#xff09;与不带包装&#xff08;wob&#xff09;状态&#xff0c;共对应4592张图片的…

作者头像 李华
网站建设 2026/9/27 23:09:22

YOLOv8布匹缺陷检测实战:污渍破洞精准识别与CPU部署

简介&#xff1a;本资源是一套基于YOLOv8实现的布匹缺陷&#xff08;污渍、破洞&#xff09;智能检测系统&#xff0c;面向计算机、人工智能、自动化等专业的在校学生、教师及企业开发者&#xff0c;适用于毕业设计、课程设计、大作业与工业质检入门实践。包内含完整Python源码…

作者头像 李华
网站建设 2026/9/27 23:05:45

YOLOv10打架行为检测实战:权重、数据集与全流程部署指南

简介&#xff1a;本资源面向计算机视觉学习者与安防场景开发者&#xff0c;提供一套可直接落地的YOLOv10打架行为检测方案&#xff0c;解决从数据准备到模型推理的完整链路问题。包内包含已训练好的权重文件&#xff0c;加载后即可对图像或视频进行正常与打架两类行为推理&…

作者头像 李华
网站建设 2026/9/27 23:05:23

Java外卖系统课程设计:Servlet+JSP+MySQL全流程源码解析

简介&#xff1a;一套基于Java技术栈的外卖系统APP完整项目&#xff0c;面向Java/Android方向的课程设计、毕业设计及自主提升。项目仿照主流外卖应用&#xff0c;覆盖用户下单、商家接单、配送员配送等核心业务闭环&#xff0c;后端基于Spring Boot构建&#xff0c;数据存储采…

作者头像 李华
网站建设 2026/9/27 23:03:35

压缩感知SAR成像:从稀疏重构到工程落地的全流程解析

简介&#xff1a;基于压缩感知理论的合成孔径雷达成像算法MATLAB实现&#xff0c;面向雷达信号处理、遥感成像与压缩感知方向的初学者及科研人员。针对传统SAR成像中采样数据量大、存储与处理成本高的问题&#xff0c;算法将压缩感知引入SAR成像流程&#xff0c;依次完成稀疏表…

作者头像 李华