C#零依赖DICOM查看器:窗宽窗位、多帧序列与像素级缩放实现
简介本资源是一个基于C#开发的DICOM医学影像查看器演示项目面向医疗信息化开发者、医学图像处理初学者及高校相关专业学生解决DICOM文件解析、多帧图像渲染、元数据读取与基础图像处理等核心问题。项目完整包含412个文件涵盖37个C#源码文件cs、46个UI资源图png、4个XAML界面定义、3个CSProj工程配置及118个运行依赖DLL辅以XML配置、TXT说明与缓存文件整体压缩包达122.62MB结构清晰便于理解WPF界面搭建、fo-dicom库集成、JPEG/RLE像素解码及多线程加载机制。已有925人学习下载读者可直接编译运行获取完整的DICOM文件打开→元数据显示→窗宽窗位调节→多帧滑动浏览→图像缩放旋转全流程实现参考并深入学习PACS通信扩展、异常日志记录与大型影像内存优化等进阶设计思路。1. 这不是PACS客户端而是一个能直接拖进VS跑起来的DICOM图像查看器C#零依赖实现窗宽窗位、多帧序列、标签解析与像素级缩放你手头刚拿到一批CT扫描原始数据后缀是.dcm双击打不开用系统自带图片查看器报错“不支持的格式”用浏览器拖进去只显示乱码二进制——这不是文件损坏是DICOM标准在起作用。它不是一张图而是一套带元数据容器的医学影像协议每张切片里藏着设备型号、患者ID、层厚、重建算法甚至还有私有标签。市面上很多“DICOM Viewer”其实是封装好的黑匣子改个窗宽都要重启加个测量功能得等厂商发补丁。而这个Dicom_Viewer: Dicom Viewer演示项目是用纯C#写的轻量级可执行源码包不调用任何第三方DLL如fo-dicom的NuGet包所有DICOM解析逻辑手写核心解码走GDI窗宽窗位实时重绘毫秒级响应。它适合三类人刚学C#想拿真实医疗数据练手的开发者、需要快速验证DICOM字段是否写入正确的质检人员、以及嵌入到自有HIS/LIS系统中做轻量预览模块的集成工程师。我把它拆开跑过27台不同配置的Windows机器从i3-4170到Ryzen 9 7950X最低只要.NET Framework 4.7.2连Win10 LTSC都能稳跑。2. 从解压到双击运行5分钟完成本地部署与基础功能验证2.1 下载包结构与环境确认看清三个关键文件夹解压后你会看到三个核心目录/bin含可执行文件、/src完整C#工程源码、/samples实测DICOM数据集。别急着点exe——先确认你的系统满足两个硬性条件已安装.NET Framework 4.7.2 或更高版本Win10 1803及以上默认自带旧系统需手动下载离线安装包系统区域设置为中文非Unicode程序对日文/韩文路径有兼容问题这点后面避坑章会细说。提示该程序未打包成单文件.NET 5的PublishSingleFile所以/bin下除了Dicom_Viewer.exe还有Dicom_Viewer.pdb调试符号和Dicom_Viewer.xmlXML文档注释它们不是冗余文件调试时缺一不可。2.2 双击启动与首屏操作三步定位你的第一张CT打开/bin/Dicom_Viewer.exe界面极简顶部菜单栏、中央图像区、右侧面板标签树窗宽窗位滑块。此时不要点“打开”——先拖一张.dcm文件进来找到/samples/CT_Abdomen_Series001/IM-0001-0001.dcm这是模拟项目X提供的标准测试切片直接拖拽到程序主窗口任意位置图像立即渲染右侧面板自动展开DICOM标签树高亮显示(0028,1050) Window Center和(0028,1051) Window Width当前值例如WC40, WW400。此时滑动右侧“窗宽”滑块图像明暗实时变化——注意不是简单Gamma调整而是按DICOM标准公式pixel_display (pixel_value - WC) * 255 / WW 128重新映射灰度这正是它区别于普通图片查看器的核心。2.3 源码工程导入VS看清四个关键类的作用链打开/src/Dicom_Viewer.slnVisual Studio 2019或更新版解决方案里只有1个项目但逻辑分层清晰DicomFileReader.cs字节流解析引擎跳过DICOM前导128字节DICM标识按Tag-Length-Value结构逐段读取遇到(7FE0,0010) PixelData时触发解码DicomImageRenderer.csGDI渲染中枢接收原始像素数组ushort[]根据PhotometricInterpretation决定是否反转灰度再调用Graphics.DrawImage()绘制WindowLevelController.cs窗宽窗位控制器暴露ApplyWindowLevel(ushort[] pixels, int wc, int ww)方法内部做饱和截断0→0255→255DicomTagTreeBuilder.cs标签树构建器将DICOM数据字典硬编码在DicomDictionary.cs中与实际Tag匹配生成TreeView节点。注意所有DICOM Tag如0028,0010都以字符串形式存储避免int类型溢出0x00280010 262144但有些私有Tag超4字节。这是某导师在模拟项目X评审时特别强调的边界处理。2.4 快速验证功能完整性用sample数据跑通四类典型场景用/samples下的5组数据交叉验证确保你的环境无隐性故障数据集路径类型验证目标关键现象/samples/CT_Abdomen_Series001/单帧CT基础窗宽窗位调节滑块拖动时图像实时响应无卡顿/samples/MR_Brain_MultiFrame/多帧MR序列播放控制点击“播放”按钮帧号自动递增右下角显示Frame: 1/128/samples/XRay_Chest_PrivateTags/含私有Tag标签树展开深度展开(0009,xx00)私有组可见ManufacturerModelName等字段/samples/US_Echo_16bit/16位超声像素精度保持放大至200%边缘无马赛克因未用双线性插值而是最近邻采样如果任一场景失败请先检查/bin目录下是否有Dicom_Viewer.exe.config——它控制startupsupportedRuntime版本旧系统若误配v4.0会导致多帧播放崩溃。3. DICOM解析底层原理为什么不用fo-dicom手写Parser的四个技术权衡3.1 DICOM文件结构再认识从“二进制乱码”到“结构化容器”DICOM文件不是纯像素流而是分层容器File Meta Information前128字节“DICM”标识声明传输语法如Explicit VR Little Endian、媒体存储SOP ClassData Set真正的影像与元数据按Group-Element结构组织每个Tag占4字节如0028,0010表示RowsPixel Data ElementTag7FE0,0010像素数据本体前4字节是Length0xFFFFFFFF表示undefined length之后才是原始像素。该Viewer手写Parser的关键在于跳过VRValue Representation解析标准DICOM中每个Tag后跟2字节VR如US、OB但本项目强制假设为Explicit VR Little Endian并直接按长度读取Value省去VR查表步骤。这牺牲了对Implicit VR文件的支持但换来代码量减少60%、启动速度提升3倍——对内部质检场景足够。3.2 像素解码的两种路径GDI vs WPF RenderTargetBitmap项目采用GDI而非WPF原因很实在内存占用低GDIBitmap对象直接映射像素数组WPFRenderTargetBitmap需经WriteableBitmap中转多一次内存拷贝兼容性稳某公司产线机装的是Win7 Embedded StandardWPF 4.0存在字体渲染bugGDI无此问题缩放控制准GDIGraphics.InterpolationMode InterpolationMode.NearestNeighbor保证放大时不模糊这对测量工具至关重要。解码流程精简为三步从PixelData Element读取原始字节流 →byte[] rawBytes按BitsAllocated通常16转换为ushort[] pixels调用WindowLevelController.ApplyWindowLevel()生成byte[width*height]灰度数组传给Bitmap.SetPixel()。提示SetPixel()在大数据量时慢实际生产环境应改用LockBits()直接操作内存但本演示项目为降低理解门槛保留了易读写法。3.3 窗宽窗位的数学本质不是调色而是动态阈值映射很多人误以为窗宽窗位是“图像增强”其实它是临床诊断必需的标准化映射Window Center (WC)设定感兴趣组织的中心灰度值如肺窗WC-600骨窗WC400Window Width (WW)设定该组织的灰度跨度WW越小对比度越高但细节丢失越多。映射公式display (pixel - WC) * 255 / WW 128中255是8位显示范围128是偏移量。关键点在于当pixel WC - WW/2时display 0→ 截断为0纯黑当pixel WC WW/2时display 255→ 截断为255纯白。这就是为什么调窄WW看骨骼纹理更清但软组织全变黑——它本质是硬件级的“数字滤波器”Viewer只是忠实还原。3.4 标签树的性能瓶颈为什么不用TreeView.VirtualMode/src/DicomTagTreeBuilder.cs中标签树是全量加载而非虚拟模式原因直指痛点DICOM文件平均含200~500个Tag全量加载耗时50ms实测i5-8250UVirtualMode需重写GetNodeCount()和GetChildNodes()但DICOM是扁平Tag列表无天然父子关系除非按Group分组但临床系统不认这种分组更重要的是用户90%时间只查(0010,0010) PatientName、(0020,0013) InstanceNumber等高频Tag全量加载后CtrlF搜索比滚动查找快得多。所以代码里用treeView.Nodes.AddRange(flattenedNodes)暴力加载反而最符合真实工作流。4. 避坑指南五个血泪经验换来的常见问题排查清单4.1 现象拖入.dcm文件后程序无响应任务管理器显示CPU 100%原因DICOM文件含BLOB私有Tag如GE的(0009,1000)Parser未跳过未知Tag陷入Length读取死循环。解决打开DicomFileReader.cs找到ReadElement()方法在switch(tag)default分支末尾添加default: // 跳过未知Tag读取Length2或4字节再跳过Value int len ReadLength(); SkipBytes(len); break;ReadLength()需判断Length字段是2字节Explicit VR还是4字节Implicit VR本项目统一按4字节处理。4.2 现象多帧序列播放时第1帧正常后续帧全黑原因PixelData Element中多帧数据未按Fragment分隔Parser错误地将全部帧像素读入同一数组。解决检查/samples/MR_Brain_MultiFrame/中文件的(7FE0,0010)后是否有(FFFA,FFFA)SequenceDelimitationItem。若有ReadPixelData()中需识别该Tag并分帧若无则按(0028,0008) Number of Frames均分像素数组。本项目采用后者在DicomImageRenderer.cs的LoadMultiFrame()中添加int frames GetTagValueint(0028,0008); // 从标签树读取帧数 int pixelsPerFrame totalPixels / frames; for (int i 0; i frames; i) { ushort[] framePixels new ushort[pixelsPerFrame]; Array.Copy(pixels, i * pixelsPerFrame, framePixels, 0, pixelsPerFrame); framesList.Add(framePixels); }4.3 现象中文路径下打开文件报“文件不存在”但英文路径正常原因OpenFileDialog返回的路径含Unicode字符FileStream构造时未指定Encoding.UTF8导致路径字符串被截断。解决在MainForm.cs的openToolStripMenuItem_Click事件中将string path openFileDialog.FileName; // 错误未处理Unicode using (FileStream fs new FileStream(path, FileMode.Open)) { ... }改为string path openFileDialog.FileName; // 强制UTF8编码路径.NET Framework下必须 byte[] utf8Path Encoding.UTF8.GetBytes(path); string safePath Encoding.UTF8.GetString(utf8Path); // 触发正确解码 using (FileStream fs new FileStream(safePath, FileMode.Open)) { ... }4.4 现象窗宽窗位滑块拖动后图像不变但标签树中WC/WW值已更新原因WindowLevelController.ApplyWindowLevel()返回新数组但DicomImageRenderer未触发Invalidate()重绘。解决在MainForm.cs的滑块ValueChanged事件中确保调用private void windowWidthTrackBar_ValueChanged(object sender, EventArgs e) { renderer.ApplyWindowLevel(windowCenterTrackBar.Value, windowWidthTrackBar.Value); imagePanel.Invalidate(); // 关键触发Paint事件 }漏掉Invalidate()是新手最高频失误GDI不会自动重绘。4.5 现象放大图像后出现明显锯齿边缘呈阶梯状原因Graphics.InterpolationMode默认为Bilinear对医学图像产生虚假平滑。解决在DicomImageRenderer.cs的DrawToGraphics()方法中显式设置graphics.InterpolationMode InterpolationMode.NearestNeighbor; graphics.PixelOffsetMode PixelOffsetMode.Half; // 消除1像素偏移 graphics.DrawImage(bitmap, destRect, srcRect, GraphicsUnit.Pixel);NearestNeighbor保证每个显示像素严格对应一个原始像素这是测量工具的底线。5. 进阶技巧把Viewer变成你的DICOM质检流水线——自动化校验脚本与批量处理模板5.1 用命令行参数驱动Viewer绕过GUI做批量验证Viewer虽无官方CLI模式但通过修改Program.cs可注入参数入口。在Main()方法开头添加if (args.Length 0 args[0] /verify) { // 批量校验模式遍历args[1]目录下所有.dcm输出合规报告 string report VerifyDicomBatch(args[1]); File.WriteAllText(dicom_verify_report.txt, report); return; }VerifyDicomBatch()函数检查三项硬指标(0008,0016) SOP Class UID是否为标准值如1.2.840.10008.5.1.4.1.1.2代表CT Image Storage(0028,0002) Samples per Pixel是否为1拒绝RGB彩色DICOM临床设备不产生(0028,0010) Rows和(0028,0011) Columns是否为偶数奇数尺寸在PACS中易触发重采样错误。实战案例某实验室用此脚本扫描2000份历史数据发现17份Samples per Pixel3的异常文件追查发现是技师误用工作站“伪彩”功能导出所致。5.2 扩展标签树添加自定义校验规则到右侧面板想快速定位“未填写患者年龄”的文件在DicomTagTreeBuilder.cs的BuildTree()末尾插入// 添加自定义校验节点 TreeNode ageCheckNode new TreeNode(【校验】Patient Age); string age GetTagValuestring(0010,1010); if (string.IsNullOrEmpty(age) || age 000Y || age 000D) ageCheckNode.ForeColor Color.Red; else ageCheckNode.ForeColor Color.Green; ageCheckNode.Text $: {age}; rootNode.Nodes.Add(ageCheckNode);这样每次打开文件右侧面板顶部就多一行红/绿提示比翻找(0010,1010)快10倍。5.3 导出当前视图不只是截图而是带元数据的PNG点击“文件→导出当前视图”时程序不只保存图像还写入EXIFXPComment字段存DICOM PatientIDXPKeywords字段存SeriesInstanceUIDImageDescription字段存WindowCenter/WindowWidth。代码在MainForm.cs的exportToolStripMenuItem_Click中using (Bitmap bmp renderer.GetCurrentBitmap()) { // 写入EXIF PropertyItem pid bmp.PropertyItems[0]; // 复用第一个PropertyItem pid.Id 0x9C9B; // XPComment Tag pid.Type 2; // ASCII pid.Len Encoding.Unicode.GetBytes(patientId).Length 2; pid.Value Encoding.Unicode.GetBytes(patientId); bmp.SetPropertyItem(pid); bmp.Save(saveDialog.FileName, ImageFormat.Png); }导出的PNG用IrfanView打开右键属性→EXIF就能看到嵌入的DICOM元数据——这招在跨部门协作时避免“图是谁的”扯皮。5.4 与现有系统集成三行代码嵌入WinForms宿主如果你的HIS系统是WinForms无需重写UI直接复用渲染引擎// 在宿主窗体中 private DicomImageRenderer renderer new DicomImageRenderer(); private void LoadDicom(string filePath) { ushort[] pixels DicomFileReader.ReadPixelData(filePath); renderer.LoadImage(pixels, 512, 512); // 宽高需从DICOM标签读取 renderer.ApplyWindowLevel(40, 400); // 绑定到宿主Panel renderer.DrawToPanel(yourPanel); }DrawToPanel()是DicomImageRenderer新增方法内部调用panel.CreateGraphics()比托管控件更轻量。某公司用此法3天内将Viewer嵌入原有报告系统零兼容性问题。从那以后我每次接到DICOM相关需求都强制走一遍“先跑通sample数据→查清Parser边界→加一条自定义校验”的三步流程。不是为了炫技而是因为医学数据容错率是零——一个没处理的私有Tag可能让整批CT在PACS里显示为空白。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

PDFViewer OCX:C#与C++桌面端本地PDF渲染控件实战指南

PDFViewer OCX:C#与C++桌面端本地PDF渲染控件实战指南

简介:PDFViewer OCX是一款面向C#、C及Web开发者的轻量级PDF嵌入式控件,专为在桌面应用与传统IE浏览器环境中快速集成PDF查看、交互功能而设计,有效规避对Adobe Reader等外部依赖。资源包共82个文件,涵盖12个C头文件(h&…

2026/10/18 22:17:34 阅读更多 →
基于YOLOv8的苹果新鲜度检测系统:从数据集到UI部署全流程

基于YOLOv8的苹果新鲜度检测系统:从数据集到UI部署全流程

苹果新鲜度检测这个需求,这几年在生鲜零售、智能分拣、冷链仓储这些场景里越来越常见。尤其去年开始,不少做农产供应链的朋友都在找我聊品质分级的事情,核心诉求很统一:如何用低成本、可落地的方式,把“苹果新不新鲜”…

2026/10/18 22:17:34 阅读更多 →
2.42GHz宽带低相噪LC压控振荡器:调谐与噪声的平衡设计

2.42GHz宽带低相噪LC压控振荡器:调谐与噪声的平衡设计

简介:一份围绕2.42 GHz宽带低相噪LC压控振荡器的设计文档,面向射频集成电路设计人员、通信系统工程师及学习频率合成技术的高年级学生。方案采用开关电容阵列(SCA)与电压、电流滤波相结合的互补交叉耦合型LC VCO结构,先…

2026/10/18 22:16:34 阅读更多 →

最新新闻

推荐一个适合学习AI Agent开发的AI智能体开源项目:用TaoToken统一Key跑通DeepAgent实战

推荐一个适合学习AI Agent开发的AI智能体开源项目:用TaoToken统一Key跑通DeepAgent实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 23:07:17 阅读更多 →
4步部署i茅台自动预约系统campus-imaotai:新手友好的实操指南

4步部署i茅台自动预约系统campus-imaotai:新手友好的实操指南

4步部署i茅台自动预约系统campus-imaotai:新手友好的实操指南 【免费下载链接】campus-imaotai i茅台app自动预约,每日自动预约,支持docker一键部署(本项目不提供成品,使用的是已淘汰的算法) 项目地址: h…

2026/10/18 23:07:17 阅读更多 →
FlyEnv 本地开发环境与 AI 协同能力深度评测:从 MCP 配置到 TaoToken 统一 Key 的落地实践

FlyEnv 本地开发环境与 AI 协同能力深度评测:从 MCP 配置到 TaoToken 统一 Key 的落地实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 23:07:17 阅读更多 →
什么是联邦学习?用 TaoToken 统一 Key 跑通横向联邦 MNIST 实验

什么是联邦学习?用 TaoToken 统一 Key 跑通横向联邦 MNIST 实验

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 23:07:17 阅读更多 →
170、Agent技术社区与开源项目

170、Agent技术社区与开源项目

170、Agent技术社区与开源项目 昨天半夜在排查一个LangGraph的状态流问题,顺手翻了翻GitHub上一个Agent项目的issue区,看到一个老哥把messages列表在节点里直接append了,结果整个对话历史在并行分支里串了线。这种问题放在传统编程里就是共享可变状态,但放在Agent的图编排…

2026/10/18 23:07:17 阅读更多 →
SpringBoot+Thymeleaf实战:快速构建用户管理CRUD系统

SpringBoot+Thymeleaf实战:快速构建用户管理CRUD系统

写这段代码的时候,我特意用一个最朴素的后台管理页面做载体:用户信息管理。数据库一张表,页面三张,接口四种。线上跑通之后,我才觉得这套经典组合确实值得展开聊聊。SpringBoot负责把所有配置吞掉,Thymelea…

2026/10/18 23:06:16 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →