新闻详情

新闻详情

首页 / 资讯中心 / 详情

C# 与 OnnxRuntime 部署 SAM3:可提示概念分割的工程落地指南

发布时间:2026/10/2 1:18:58来源:尧图网络
C# 与 OnnxRuntime 部署 SAM3:可提示概念分割的工程落地指南
简介基于C#与OnnxRuntime部署SAM3模型实现可提示概念分割的完整资源包面向需要将深度学习分割能力集成到桌面、企业级或跨平台应用中的C#开发者尤其适合已有一定视觉基础并希望在真实项目中落地的技术人员。SAM3继承并优化了Segment Anything Model的提示机制用户通过点击、框选等线索即可引导模型完成目标提取与背景分离在自动驾驶、医学影像、视频监控等场景都有应用价值。资源包大小约653.87MB共315个文件按工程、依赖、配置与文档组织dll、lib、nupkg等库文件保障推理运行cs、sln、csproj组成可直接加载的C#工程xml、config、json等配置文件提供服务参数pdb、targets、props辅助调试与构建md、txt、png则提供说明文档和示意图目录结构清晰便于查阅。包内还配有可运行程序、依赖资源和编译运行指引帮助开发者快速验证从模型加载到提示分割输出的完整流程。资源包已有122人浏览/学习适合希望快速掌握SAM3部署方法并开展二次开发的C#工程师参考。1. 用 C# 在 OnnxRuntime 里跑 SAM3可提示概念分割的落地姿势做 C# 上位机里的视觉分割最难受的往往不是模型效果而是模型根本跑不起来。算法同事给的 SAM3 权重是 PyTorch 格式调试时开着 Python 控制台很顺手但一进到 .NET 进程就变成黑匣子。这套资源解决的就是这件事它把 SAM3 的可提示概念分割完整跑在 C# OnnxRuntime 里模型切成 ONNX 格式进程内推理不上云、不依赖 Python 服务。所谓“可提示概念分割”意思是你不光能给它一个框或一个点去抠目标还能按“概念”去分割——给模型一个语义提示它把画面里符合这个概念的区域成片地拎出来。对于 Windows 桌面工具、上位机视觉预处理、产线质检二次确认这几类场景这个资源能省掉至少两周的模型适配工作量。下面从模型管线、环境准备、C# 实现到高频翻车点逐层拆开。2. SAM3 的 ONNX 推理管线先探清模型进出再动手2.1 SAM3 与 SAM2 的差异为什么“概念”不再是名词SAM2 解决的是“分割一切”的视频化延展输入输出仍然围绕点、框、掩码这类低层几何提示。SAM3 往前多走了一步它把分割对象从“某个像素块”上升到“某个概念”。概念可以是“人”“车辆”“墙面裂缝”也可以是一个短语对应的语义区域。过去你要先检测再分割现在一个模型直接给出概念区域。这对工程选型影响很大。如果你只做固定类别分割用 YOLO 传统分割就能对付但概念集合不固定、类别粒度会变化的场景SAM3 这种可提示概念分割才有意义。我见过不少同学拿到 SAM3 的 ONNX 文件后第一反应是找“类别标签表”——没有。它的标签不是写在模型里而是通过提示和概念嵌入映射进来的。工程上要接受一个事实SAM3 的前处理不再只是 resize 加 normalize而是要把“概念提示”编码成与空间位置相关的张量。提示可以是点、框、文本嵌入也可能是一组组合提示。C# 端实现的重点因此分成两半一半是图像的常规预处理另一半是提示的坐标转换和标签约定。这套资源里最值钱的部分是把提示到张量的映射关系写死了你不用去翻论文复现直接按它的输入张量约定填数就行。2.2 ONNX 输入输出约定张量名称与动态轴SAM3 这类模型直接导出单个 ONNX 文件会很大而且图像编码器和掩码解码器的更新频率不一样。常见的做法也是这套包里采用的做法是拆成两个 ONNX图像编码器吃原图输出图像嵌入image embedding掩码解码器吃图像嵌入加提示输出多路掩码和 IoU 预测图像编码器的输入输出方向张量名形状说明输入image[1, 3, H, W]RGB归一化到 0~1输出image_embedding[1, 256, 64, 64]特征维度与网格尺寸随导出配置变化掩码解码器的输入输出方向张量名形状说明输入image_embedding[1, 256, 64, 64]编码器输出输入point_coords[1, N, 2]归一化后的提示坐标N 为点数输入point_labels[1, N]提示标签标注正负点或框角点输出masks[1, 4, 256, 256]低分辨率掩码 logits4 路候选输出iou_predictions[1, 4]每路掩码的置信度注意 masks 输出不是原图尺寸而是低分辨率 256×256。上采样到原图是后处理阶段的事不属于模型职责。很多 C# 新手在这里卡住以为模型出错了其实是把后处理漏了。动态轴方面point_coords 和 point_labels 的 N 维度必须设成动态因为每次推理的点数可能不同。图像长宽也可以设成动态但实际项目中固定 1024 更省心能减少 ONNX Runtime 的形状推导开销。2.3 为什么选 OnnxRuntime 而不是 Python 推理服务OnnxRuntime 和 ONNX 的关系得先分清ONNX 是模型格式OnnxRuntime 是推理引擎。前者解决“模型怎么存”后者解决“模型怎么跑”。很多 C# 工程选型时会纠结要不要起一个 Python Flask 服务让 C# 走 HTTP 调用。我一般不建议这么做除非你们团队有专门的算法服务化基础设施。理由有三个。第一进程内推理省掉序列化和网络开销单帧分割的端到端延迟能低 8~15 毫秒这对实时预览很重要第二部署形态简单一个 EXE 加两个 ONNX 文件就能交付客户机器上不用装 Python 环境第三调试透明C# 里能直接看到 session 的输入输出元数据配合 OnnxRuntime 日志能定位张量名不匹配这类问题。资源包里用的就是 OnnxRuntime 官方 NuGet 包动态库随包分发不需要额外注册 COM 组件这对 Windows 环境的上位机项目优势明显。3. 环境与模型准备从 .pth 权重到可加载的 .onnx3.1 版本组合.NET、OnnxRuntime 与 CUDA 的匹配关系先把版本矩阵列出来这是最容易翻车的地方。OnnxRuntime 的 GPU 包对 CUDA、cuDNN 有严格的版本要求配错了就是运行时报错或者静默走 CPU。组件建议版本说明.NET6.0 或 8.0两者都支持9.0 建议等 OnnxRuntime 验证过再用Microsoft.ML.OnnxRuntime1.17 以上CPU 推理选这个包名Microsoft.ML.OnnxRuntime.Gpu与 CUDA 版本对应GPU 包和 CPU 包不能同时引用CUDA11.8 或 12.x按 OnnxRuntime 官方 release note 对齐OpenCvSharp44.8 以上处理图像缩放、填充、阈值化Python3.10只用于导出 ONNX 脚本运行时不需要CPU 原型验证阶段直接用 Microsoft.ML.OnnxRuntime 就行别一上来就折腾 GPU。等 CPU 链路完全通了再切 GPU 包这样能把“CUDA 版本问题”和“代码 bug”分开排查。3.2 权重导出 ONNX带动态轴的导出脚本导出是模型侧的事但 C# 工程师最好也能看懂脚本至少要知道动态轴设在哪、opset 为什么不能太低。下面是按“拆分导出”思路写的脚本核心段import torch from sam3 import build_sam3 checkpoint ./sam3_concept.pt model build_sam3(checkpointcheckpoint) model.eval() image_encoder model.image_encoder mask_decoder model.mask_decoder # 导编码器输入图像尺寸设动态方便适配不同分辨率 dummy_img torch.randn(1, 3, 1024, 1024) torch.onnx.export( image_encoder, dummy_img, sam3_image_encoder.onnx, input_names[image], output_names[image_embedding], dynamic_axes{image: {2: H, 3: W}}, opset_version17, ) # 导解码器提示点数量设为动态 token_nums 2 # 示例里用两个提示点 dummy_embedding torch.randn(1, 256, 64, 64) dummy_points torch.randn(1, token_nums, 2) dummy_labels torch.randint(0, 4, (1, token_nums)) torch.onnx.export( mask_decoder, (dummy_embedding, dummy_points, dummy_labels), sam3_mask_decoder.onnx, input_names[image_embedding, point_coords, point_labels], output_names[masks, iou_predictions], dynamic_axes{ point_coords: {0: B, 1: N}, point_labels: {0: B, 1: N}, }, opset_version17, ) print(done)这段脚本里最需要注意的是 opset_version。17 是 OnnxRuntime 1.14 之后很稳的版本太低会丢失一些算子映射太高则要求 OnnxRuntime 版本跟上。C# 侧如果用 1.17opset 17 完全没问题。point_labels 的数值来自模型导出时约定的标签编码正点标 1负点标 0框的左上角点和右下角点分别标 2 和 3。不同版本 SAM3 的标签映射可能略有差异C# 端编码提示时一定要和这个约定对齐否则会出现掩码全黑、分割结果偏移这类疑难问题。3.3 C# 侧初始化SessionOptions 与执行提供程序C# 里加载模型的第一步是建 InferenceSession。这里有几个参数值得单独讲GraphOptimizationLevel、日志级别以及执行提供程序的添加顺序。using Microsoft.ML.OnnxRuntime; var so new SessionOptions { GraphOptimizationLevel GraphOptimizationLevel.ORT_ENABLE_ALL, LogSeverityLevel OrtLoggingLevel.ORT_LOGGING_LEVEL_WARNING }; // CPU 原型阶段先不启用 CUDA // var cudaOptions new OrtCUDAProviderOptions(); // so.AppendExecutionProvider_CUDA(cudaOptions); using var encoder new InferenceSession(sam3_image_encoder.onnx, so); using var decoder new InferenceSession(sam3_mask_decoder.onnx, so); Console.WriteLine(encoder inputs: string.Join(,, encoder.InputMetadata.Keys)); Console.WriteLine(decoder inputs: string.Join(,, decoder.InputMetadata.Keys));GraphOptimizationLevel 建议直接开 ORT_ENABLE_ALL让 OnnxRuntime 做常量折叠、算子融合对动态轴模型也有好处。日志级别设成 WARNING避免每次推理都刷屏但排查问题时可以临时改成 INFO。执行提供程序这块C# 和 C 的坑一样需要在创建 Session 前添加。如果 Session 已创建再改 Provider是不生效的。另外GPU 包和 CPU 包的 NuGet 包名不同引用错了会直接导致加载失败。初始化完成后强烈建议先打印 InputMetadata 的键名和 ONNX 模型里的张量名对一遍。这两个名字不一致是最常见、也最浪费时间的错误。4. C# 实现可提示概念分割核心代码与边界参数4.1 预处理等比缩放、填充与坐标归一化SAM3 的图像编码器一般要求长边对齐到 1024并且宽高最好是 64 的倍数。直接把原图 resize 过去会破坏长宽比导致分割边界的空间对应关系漂移。正确做法是等比缩放长边到 1024再填充到 64 的倍数。using OpenCvSharp; static (Mat canvas, float scale, int padTop, int padLeft) PrepareImage(Mat src, int target 1024) { int h src.Rows; int w src.Cols; float scale target * 1f / Math.Max(h, w); int rw (int)Math.Round(w * scale); int rh (int)Math.Round(h * scale); var resized new Mat(); Cv2.Resize(src, resized, new Size(rw, rh), 0, 0, InterpolationFlags.Linear); int padW (int)(Math.Ceiling(rw / 64.0) * 64); int padH (int)(Math.Ceiling(rh / 64.0) * 64); int padTop (padH - rh) / 2; int padLeft (padW - rw) / 2; var canvas Mat.Zeros(padH, padW, MatType.CV_8UC3); var roi new Rect(padLeft, padTop, rw, rh); resized.CopyTo(new Mat(canvas, roi)); return (canvas, scale, padTop, padLeft); }这里返回 scale、padTop、padLeft 三个值不是为了好看而是后面提示坐标归一化必须要用。很多实现只返回缩放后的图把坐标转换忽略掉结果点提示全都偏了。Resize 时插值方式选 Linear不要选 Nearest。SAM3 这类分割模型对像素级位置敏感最近邻插值会在边缘产生锯齿影响掩码质量。4.2 构建输入张量并执行 Run预处理完成后要把 Mat 转成 ONNX Runtime 认识的 DenseTensor。注意通道顺序模型要的是 RGBOpenCV 默认读进来是 BGR必须转换。using Microsoft.ML.OnnxRuntime.Tensors; using System.Runtime.InteropServices; static DenseTensorfloat MatToTensor(Mat bgr) { var rgb new Mat(); Cv2.CvtColor(bgr, rgb, ColorConversionCodes.BGR2RGB); int h rgb.Rows, w rgb.Cols; var tensor new DenseTensorfloat(new[] { 1, 3, h, w }); var data new byte[h * w * 3]; Marshal.Copy(rgb.Data, data, 0, data.Length); var span tensor.Buffer.Span; int idx 0; for (int c 0; c 3; c) { for (int y 0; y h; y) { for (int x 0; x w; x) { span[idx] data[(y * w x) * 3 c] / 255.0f; } } } return tensor; }数据排列要特别注意模型输入是 CHWOpenCV 的 Mat 内存布局是 HWC。如果直接按行拷贝内存不重排通道和空间维度模型会“看到”完全错乱的图像。上面代码里三重循环就是做这个重排。编码器推理using Microsoft.ML.OnnxRuntime; static float[] RunEncoder(InferenceSession encoder, DenseTensorfloat imageTensor) { var inputs new ListNamedOnnxValue { NamedOnnxValue.CreateFromTensor(image, imageTensor) }; using var output encoder.Run(inputs); var embedding output.ElementAt(0).AsTensorfloat(); return embedding.ToArray(); }using var output这段不能省。OnnxRuntime 的 Run 返回的是非托管资源不释放会累积内存泄漏。测试程序短时间跑看不出来放到产线里跑一整天就会爆内存。解码器推理要同时传入嵌入和提示坐标static (float[] masks, float[] ious) RunDecoder( InferenceSession decoder, float[] imageEmbedding, float[] pointCoords, float[] pointLabels, int pointNum) { var embTensor new DenseTensorfloat(imageEmbedding, new[] { 1, 256, 64, 64 }); var ptsTensor new DenseTensorfloat(pointCoords, new[] { 1, pointNum, 2 }); var lblTensor new DenseTensorfloat(pointLabels, new[] { 1, pointNum }); var inputs new ListNamedOnnxValue { NamedOnnxValue.CreateFromTensor(image_embedding, embTensor), NamedOnnxValue.CreateFromTensor(point_coords, ptsTensor), NamedOnnxValue.CreateFromTensor(point_labels, lblTensor) }; using var results decoder.Run(inputs); var masksTensor results.ElementAt(0).AsTensorfloat(); var iousTensor results.ElementAt(1).AsTensorfloat(); return (masksTensor.ToArray(), iousTensor.ToArray()); }pointCoords 里存的是归一化后的坐标pointLabels 存的是提示类型标签。这里有个容易懵的点模型输出的 masks 是 4 路候选掩码每路对应一个 iou 分数不是直接输出最终掩码。选择哪一路由后处理决定。提示如果你的资源包模型输入名不是point_coords打印decoder.InputMetadata.Keys以实际为准。ONNX 模型里张量名可以随意定义脚本示例与资源包约定一致时才能直接照抄。4.3 后处理掩码上采样、阈值与可视化解码器输出的 masks 是低分辨率 logits需要经过 Sigmoid 再上采样。选择 4 路候选里 IoU 分数最高的那一路作为最终掩码。using OpenCvSharp; static Mat DecodeBestMask( float[] masksLogits, float[] ious, int side, int originalW, int originalH, int padW, int padH) { int numMasks ious.Length; int bestIdx 0; float bestIoU float.MinValue; for (int i 0; i numMasks; i) { if (ious[i] bestIoU) { bestIoU ious[i]; bestIdx i; } } var chosen new float[side * side]; Array.Copy(masksLogits, bestIdx * side * side, chosen, 0, side * side); var maskMat new Mat(side, side, MatType.CV_32FC1, chosen); var resizedMat new Mat(); Cv2.Resize(maskMat, resizedMat, new Size(padW, padH), 0, 0, InterpolationFlags.Linear); var roi new Rect(0, 0, originalW, originalH); var cropped new Mat(resizedMat, roi); Mat result new Mat(); Cv2.Threshold(cropped, result, 0f, 255, ThresholdTypes.Binary); return result; }threshold 设 0是因为 logits 经过 Sigmoid 后0 正好对应概率 0.5。如果你拿到的模型输出已经过了 Sigmoid那阈值还是 0 没毛病如果是原始 logits同样用 0。这个细节在不同导出版本里都是成立的。上采样用 Linear 插值别用 Nearest。分割掩码是连续概率场Nearest 会让边缘变成锯齿状。可视化这一步别省。哪怕只在调试窗口里把掩码叠在原图上显示也比盯着数值强得多。用 OpenCvSharp 的Cv2.BitwiseAnd把掩码和原图合成能快速看出提示位置是否对应目标区域。5. 避坑清单C# OnnxRuntime 部署 SAM3 的高频翻车点5.1 AccessViolation C0000005释放顺序与对象生命周期现象程序运行几次后突然抛 AccessViolationException错误码 C0000005堆栈指向 OnnxRuntime 原生动态库。有些场景是关窗时崩溃有些是连续推理几十帧后崩溃。原因InferenceSession 或 Run 返回的张量被提前释放。典型写法是把 session 放在局部方法里创建方法结束 session 销毁但后续异步任务还在用之前 Run 的 embedding。C# 的 GC 会把托管张量回收底层原生内存就变成悬空指针。解决把两个 InferenceSession 提升为类字段生命周期和宿主窗口一致Run 的返回值用using包裹不要在异步回调里访问上一帧的 embedding 数组如果要跨帧使用先ToArray()拷贝到托管数组。5.2 输出掩码尺寸对不上低分辨率 logits 的坑现象读取results.ElementAt(0).AsTensorfloat().Dimensions发现是[1, 4, 256, 256]不是原图尺寸。于是怀疑模型输入错了开始检查预处理。原因模型设计如此。掩码解码器输出低分辨率掩码上采样是后处理的一部分不是模型缺陷。解决先打印输出 shape用输出 shape 推导 side 参数再按顺序做 上采样 → 裁剪 padding → 与原图对齐。记住一个原则模型只负责算概率场恢复到原图是工程的事。5.3 GPU Provider 加载失败CUDA 二进制不一致现象AppendExecutionProvider_CUDA没报错但推理速度没提升或者直接抛异常提示找不到 CUDA 库。原因NuGet 引用的是 CPU 版Microsoft.ML.OnnxRuntime同时又在代码里强行加 CUDA Provider或者 GPU 包的运行时库和你机器上的 CUDA 版本不一致。OnnxRuntime 的 GPU 版本对 CUDA、cuDNN 的小版本号敏感不是“装上就能用”。解决先 CPU 跑通原型再切换到 GPU 包。切换时把 CPU 包从 NuGet 移除干净确认 CUDA 版本与 OnnxRuntime 官方 release note 对应用Environment.GetEnvironmentVariable(CUDA_PATH)检查环境变量是否指向正确路径。5.4 掩码全是黑色坐标归一化的隐藏问题现象图像预处理看起来正常点提示也给了但输出掩码全黑IoU 分数还特别低。原因提示坐标没有经过缩放和填充补偿。直接把原图像素坐标塞进 point_coords模型的归一化坐标空间就错位了。Sigmoid 后概率全被压到背景区自然全黑。解决统一用这套公式转换float normX (pt.X * scale padLeft) / padW; float normY (pt.Y * scale padTop) / padH;其中 scale、padLeft、padTop、padW、padH 全部来自PrepareImage的返回。任何一个值漏传都会导致提示偏移。6. 让概念分割接入业务自动提示生成与离线验证6.1 用 YOLOv8 结果自动构造 SAM3 框提示概念分割真正落地到业务里提示不能靠人工在图上点。常见组合是 YOLO 先出目标框再把框转成 SAM3 的框提示。框提示在标签约定里会拆成两个点左上角点和右下角点。C# 侧的拼装逻辑var boxes DetectRois(frame); // 来自 YOLO 或传统 blob 检测 foreach (var box in boxes) { float x1 (box.X * scale padLeft) / padW; float y1 (box.Y * scale padTop) / padH; float x2 ((box.X box.Width) * scale padLeft) / padW; float y2 ((box.Y box.Height) * scale padTop) / padH; float[] coords { x1, y1, x2, y2 }; float[] labels { 2f, 2f, 3f, 3f }; // 调 RunDecoder 得到 mask再走 DecodeBestMask }labels 数组里 2 表示框左上角3 表示框右下角这是 SAM 系列的标准标签约定。如果你换的 SAM3 权重用了不同标签回来改这一行就行。YOLO 粗检测加 SAM3 精分割这种组合在固定场景下比单独跑 SAM3 更快也更稳。6.2 离线回归验证把“看起来不错”变成数据以前我调试分割模型习惯用肉眼看掩码叠图。后来发现这方式不靠谱一个小改动可能让 mIoU 从 0.83 掉到 0.73肉眼看图根本发现不了。从那以后我每次拿到一套概念分割工程都会先建一个离线验证目录把同一组提示、同一批测试图、同样的阈值全跑一遍输出一组对比指标指标计算方式关注点mIoU预测掩码与标注掩码的交并比均值整体分割精度Pixel Accuracy正确分类像素占比大目标占主导时需谨慎Boundary F1边缘像素的 F1 分数分割边界贴合度推理延迟编码器 解码器总耗时是否满足产线节拍标注掩码不需要太精细能区分概念区域就行。回归脚本里固定随机种子和提示坐标保证每次测试输入一致。验证通过后再合进主工程。从那以后我每次换模型权重、改预处理参数都会强制把离线回归跑一遍再交付。概念分割这种模型边界稍微偏一点在现场就是整片区域的分割错误光靠目测迟早要出事希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Java驾校模拟考试系统:Servlet+JSP+MySQL毕设实战解析 2026/10/2 2:07:53

Java驾校模拟考试系统:Servlet+JSP+MySQL毕设实战解析

简介:这是一套面向计算机、自动化等专业本科生的Java毕设级驾校理论考试模拟系统,适用于毕业设计、课程设计及期末大作业场景,帮助学生快速构建具备完整业务逻辑的C/S或B/S架构考试应用。资源包共684个文件,含327个Java后端核心类…

阅读更多 →
Leptonica+Tesseract+OpenCV 资源库:OCR 环境搭建与避坑指南 2026/10/2 2:07:47

Leptonica+Tesseract+OpenCV 资源库:OCR 环境搭建与避坑指南

简介:这份资源面向从事图像处理与OCR开发的工程师、科研人员及AI应用开发者,解决leptonica、tesseract、opencv三大库版本匹配与编译配置繁琐的问题。包内集成leptonica 1.76.0、tesseract 5.0.0与opencv 4.0.0,可直接调用,省去自…

阅读更多 →
PC微信聊天记录实时监控与API对接方案 2026/10/2 2:07:46

PC微信聊天记录实时监控与API对接方案

简介:这是一套面向开发者与科研人员的微信聊天数据实时监控与分析工具,聚焦于群聊与私聊内容的动态采集与结构化处理,适用于舆情监测、对话行为研究及教学实验等场景。资源包共16个文件,含5个核心Python脚本(如HttpSer…

阅读更多 →
用交互让读者“玩会“概念:Beautiful Article 的 interactive-explainer 文章类型实战指南 2026/10/2 2:07:40

用交互让读者“玩会“概念:Beautiful Article 的 interactive-explainer 文章类型实战指南

人工智能AI 技能/插件提示工程 【免费下载链接】garden-skills ConardLis open-source Skills collection, featuring web design, knowledge retrieval, image generation, and more. 项目地址: https://gitcode.com/GitHub_Trending/we/garden-skills 点击查看 免…

阅读更多 →
tech-interview-for-developer 技术面试备战指南:从刷题训练到现场解题的完整方法论 2026/10/2 2:07:40

tech-interview-for-developer 技术面试备战指南:从刷题训练到现场解题的完整方法论

教程知识库 【免费下载链接】tech-interview-for-developer 👶🏻 신입 개발자 전공 지식 & 기술 면접 백과사전 📖 项目地址: https://gitcode.com/GitHub_Trending/te/tech-interview-for-developer 点击查看 免费下载 本篇…

阅读更多 →
yuzu Switch 模拟器新手指南:4 步让游戏在电脑上跑起来 2026/10/2 2:07:40

yuzu Switch 模拟器新手指南:4 步让游戏在电脑上跑起来

yuzu Switch 模拟器新手指南:4 步让游戏在电脑上跑起来 【免费下载链接】yuzu 任天堂 Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/yu/yuzu 你的 Switch 游戏文件早就躺在硬盘里,主机却不在手边,再买一台又不划算。…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉