Unity模型UV缺失解决方案:CSV数据动态生成网格与自动UV映射
1. 项目概述当GPA导出的模型在Unity中“裸奔”如果你是一名Unity开发者并且你的工作流中涉及到从GPA这里通常指代一些地理空间分析、建筑信息模型或特定三维数据处理平台导出模型到Unity进行可视化或交互开发那么你很可能踩过这个坑满怀期待地将导出的模型文件如.obj或.fbx拖入Unity项目却发现模型虽然形状正确但材质贴图一片漆黑或者呈现出诡异的纯色、条纹状。检查模型的网格渲染器Mesh Renderer和材质球Material贴图明明正确引用了问题出在哪十有八九你的模型缺失了至关重要的UV坐标。简单来说UV是三维模型表面与二维贴图之间的一座桥梁。它定义了贴图上的每一个像素应该对应到模型表面的哪个位置。没有UV再精美的贴图也无法正确地“包裹”在模型上模型就像没穿衣服一样“裸奔”只能显示为默认的材质底色或通过顶点颜色简单着色。GPA类软件的核心功能在于数据处理与分析其模型导出功能有时并非为实时渲染引擎如Unity优化导致导出的网格数据可能包含顶点、三角面信息却唯独丢失或生成了无效的UV数据。这个问题看似简单实则棘手。手动为复杂模型展UV是一项耗时且需要专业技巧的工作。本项目标题中提到的“CSV2MESH工具”正是为解决这一痛点而生。它并非一个现成的、点开即用的软件而是一个解决问题的思路和可复现的技术方案通过解析从GPA中导出的、包含顶点数据的CSV文件在Unity运行时或编辑时动态重建网格并自动生成可用的UV坐标。接下来我将拆解这个方案的完整实现逻辑、核心代码、避坑要点并提供可直接集成到你项目中的实用脚本。2. 核心需求与方案选型解析2.1 为什么GPA导出的模型会缺失UV在深入解决方案前我们先搞清楚“敌人”是谁。GPA软件如ArcGIS、CityEngine、某些BIM导出工具的首要任务是保证几何精度和属性数据完整。其导出模型通常服务于专业GIS分析或CAD查看这些场景对纹理映射的实时性和美观度要求远低于游戏或实时仿真。因此导出插件可能根本不计算UV只导出顶点Vertex和面Triangle数据。使用非标准UV计算了UV但坐标系如从0到实际尺寸而非0到1、缠绕顺序或通道与Unity的Standard Shader不兼容。数据格式转换丢失在导出为.obj或.fbx的中间转换过程中UV信息被错误处理或丢弃。手动在3ds Max、Maya或Blender中重新展UV对于大量或复杂的模型来说成本极高。因此我们需要一个程序化、自动化的解决方案。2.2 方案对比编辑时处理 vs. 运行时生成面对缺失UV的模型通常有两条路编辑时处理Editor-Time在Unity编辑器内通过脚本导入模型后立即计算并填充UV数据然后保存为新的预制体或Asset。优点是一劳永逸运行时无性能开销。缺点是处理大量模型时可能耗时且原始模型文件更新后需要重新处理。运行时生成Run-Time在游戏或应用启动时动态读取模型数据如从CSV创建网格并计算UV。优点是灵活支持动态加载和更新不占用项目Asset空间。缺点是在运行时有一定CPU开销且需要管理网格的生命周期。对于从GPA导出的、结构相对规整的模型如建筑白模、地形区块、管道网络运行时生成往往更具优势。因为这些模型数据可能来自动态查询且我们通常需要将属性数据存储在CSV中与几何数据关联。CSV2MESH方案正是基于运行时生成的思想。2.3 CSV2MESH工具链的核心思路“CSV2MESH”这个名字直指核心将CSV格式的顶点数据转换为Unity的Mesh。一个典型的处理流程如下数据导出从GPA软件中将模型的顶点坐标x, y, z以CSV格式导出。每个顶点可能对应一行数据包含位置、可能的法线、颜色或自定义属性。数据解析在Unity中使用C#脚本如StreamReader或第三方CSV解析库读取CSV文件。网格重建根据解析出的顶点列表按照GPA导出的面索引顺序通常也需要从另一个CSV或特定格式中获取组装三角形的顶点索引数组triangles。UV自动生成这是最关键的一步。对于规则几何体如立方体、平面化的建筑立面可以采用投影式UV映射。最常用的是平面投影Planar Projection根据模型在世界坐标系中的边界框Bounds将XZ平面或XY平面投影到UV的(0,1)区间。材质与渲染为生成的Mesh创建或分配一个材质并应用贴图。由于UV是自动生成的贴图可能会被拉伸但对于许多分析可视化场景如显示热力、分类颜色这通常是可接受的。注意自动生成的UV质量无法与手动展UV相比可能会在非平面上产生纹理拉伸。但对于技术可视化、原型制作、属性驱动着色等场景这是一个“从无到有”、快速可用的完美方案。3. 核心细节解析与实操要点3.1 理解CSV数据结构与网格拓扑你的CSV文件格式决定了解析逻辑。常见的有两种顶点列表Vertex List每行一个顶点包含ID, X, Y, Z, (R, G, B, A)...等字段。面信息由另一个文件或通过顶点ID的隐含顺序定义。面片列表Face List每行一个三角形或多边形面包含V1_X, V1_Y, V1_Z, V2_X, V2_Y, V2_Z, V3_X, V3_Y, V3_Z...。这种格式更直接但可能包含重复顶点。在动手编码前必须用文本编辑器或Excel打开CSV文件彻底弄清其结构。一个常见的陷阱是坐标系差异。GPA软件可能使用右手坐标系如某些GIS系统而Unity使用左手坐标系Y轴向上。你可能需要在导入时对顶点坐标进行转换例如交换Y和Z轴并可能需要进行缩放。3.2 自动生成UV的算法详解这里重点介绍最实用的基于边界框的平面投影UV生成算法。假设我们为模型生成基于XZ平面的UV适用于地面建筑、地形。// 假设 vertices 是 ListVector3包含了网格的所有顶点 Vector3 minBounds new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); Vector3 maxBounds new Vector3(float.MinValue, float.MinValue, float.MinValue); // 1. 计算模型的轴对齐边界框 (AABB) foreach (Vector3 vert in vertices) { minBounds Vector3.Min(minBounds, vert); maxBounds Vector3.Max(maxBounds, vert); } Vector3 size maxBounds - minBounds; ListVector2 uvs new ListVector2(vertices.Count); // 2. 为每个顶点计算UV foreach (Vector3 vert in vertices) { // 将顶点坐标从世界空间映射到相对于边界框的[0,1]范围 // 使用X和Z坐标来对应UV的U和V float u (vert.x - minBounds.x) / size.x; float v (vert.z - minBounds.z) / size.z; // 注意这里用Z因为Unity中Y朝上 uvs.Add(new Vector2(u, v)); }为什么这样做minBounds和maxBounds定义了模型在空间中的最小包围盒。(vert.x - minBounds.x) / size.x将顶点的X坐标线性映射到0到1之间作为UV的U坐标。同理用Z坐标计算V坐标。这样整个模型在XZ平面上的投影就被“熨平”到了UV贴图的正方形上。实操心得对于高层建筑使用XZ投影会导致侧面纹理被极度拉伸。一个改进策略是按面片法向分配投影轴。计算每个三角形的法线判断其更接近哪个主轴X, Y, Z然后选择对应的两个坐标轴进行投影。虽然计算量稍大但能显著改善立方体状模型的纹理效果。3.3 性能考量与内存管理运行时动态创建网格需要注意性能合并网格Combine Meshes如果你从CSV生成了大量小网格如城市中的每个建筑直接渲染成千上万个GameObject会引发“Draw Call爆炸”。务必使用Mesh.CombineMeshes将它们合并成一个或少数几个大网格。使用List而非数组进行构造在填充顶点、UV、三角形索引时使用ListVector3等集合类型比预先分配大数组更方便因为CSV的顶点数量在读取前可能是未知的。释放旧网格如果网格需要动态更新在创建新Mesh并赋值给MeshFilter后记得销毁旧的Mesh对象Mesh.Destroy(oldMesh)防止内存泄漏。4. 完整实现从CSV到带UV的可渲染Mesh下面我将展示一个简化但功能完整的CsvToMeshGenerator脚本核心部分。假设CSV格式为每行包含一个顶点的X,Y,Z坐标。using UnityEngine; using System.Collections.Generic; using System.IO; // 用于文件读取 public class CsvToMeshGenerator : MonoBehaviour { public string csvFilePath Models/building_vertices.csv; // CSV文件在Resources或StreamingAssets中 public Material outputMaterial; // 用于渲染生成网格的材质 void Start() { Mesh mesh CreateMeshFromCSV(); if (mesh ! null) { RenderMesh(mesh); } } Mesh CreateMeshFromCSV() { // --- 1. 读取并解析CSV --- ListVector3 vertices new ListVector3(); // 注意这里需要根据你的CSV实际路径调整读取方式。 // 如果放在Resources文件夹使用TextAsset。 // 如果放在StreamingAssets或可写路径使用File.ReadAllLines。 // 此处以StreamingAssets为例 string fullPath Path.Combine(Application.streamingAssetsPath, csvFilePath); if (!File.Exists(fullPath)) { Debug.LogError(CSV file not found: fullPath); return null; } string[] lines File.ReadAllLines(fullPath); foreach (string line in lines) { // 跳过空行和可能的表头 if (string.IsNullOrWhiteSpace(line) || line.StartsWith(X)) continue; string[] values line.Split(,); if (values.Length 3) { // 解析坐标。注意可能需要根据源数据调整坐标系和缩放。 float x float.Parse(values[0]); float y float.Parse(values[1]); float z float.Parse(values[2]); // 假设源数据是Y-up需要转换为Unity的Y-up这里通常需要转换。 // 例如如果源数据是Z-up则Vector3 vert new Vector3(x, z, y); Vector3 vert new Vector3(x, y, z); vertices.Add(vert); } } if (vertices.Count 3) { Debug.LogError(Not enough vertices to form a triangle.); return null; } // --- 2. 构建三角形索引这是一个简化示例--- // 重要你的CSV必须提供面索引信息或者顶点顺序本身隐含了面信息。 // 这里假设顶点列表是按三角形顺序排列的每3个顶点一个三角形。 // 这通常不现实你需要根据实际数据格式重构此部分。 Listint triangles new Listint(); for (int i 0; i vertices.Count; i) { triangles.Add(i); } // 更真实的情况是你有另一个CSV定义面v1_index, v2_index, v3_index // 你需要读取那个文件来填充triangles列表。 // --- 3. 自动生成UV平面投影基于XZ--- ListVector2 uvs GeneratePlanarUVs(vertices); // --- 4. 创建并配置Mesh --- Mesh mesh new Mesh(); // 对于顶点数超过65535的网格需要设置索引格式 if (vertices.Count 65535) { mesh.indexFormat UnityEngine.Rendering.IndexFormat.UInt32; } mesh.SetVertices(vertices); mesh.SetTriangles(triangles, 0); // 子网格索引为0 mesh.SetUVs(0, uvs); // 设置UV通道0 mesh.RecalculateNormals(); // 自动计算法线用于光照 mesh.RecalculateBounds(); // 计算边界框 return mesh; } ListVector2 GeneratePlanarUVs(ListVector3 vertices) { // 这里使用上面3.2节描述的边界框投影算法 if (vertices null || vertices.Count 0) return new ListVector2(); Vector3 min vertices[0]; Vector3 max vertices[0]; foreach (Vector3 v in vertices) { min Vector3.Min(min, v); max Vector3.Max(max, v); } Vector3 size max - min; // 防止除零 if (size.x 0.0001f) size.x 1f; if (size.z 0.0001f) size.z 1f; ListVector2 uvs new ListVector2(vertices.Count); foreach (Vector3 vert in vertices) { float u (vert.x - min.x) / size.x; float v (vert.z - min.z) / size.z; uvs.Add(new Vector2(u, v)); } return uvs; } void RenderMesh(Mesh mesh) { GameObject meshGo new GameObject(GeneratedMesh); MeshFilter mf meshGo.AddComponentMeshFilter(); MeshRenderer mr meshGo.AddComponentMeshRenderer(); mf.mesh mesh; mr.material outputMaterial ! null ? outputMaterial : new Material(Shader.Find(Standard)); } }关键点解析csvFilePath你需要将CSV文件放在Assets/StreamingAssets文件夹下或者使用Resources.Load。StreamingAssets在构建后仍可读写更灵活。三角形索引构建这是脚本中最需要根据你的数据源定制的部分。示例中的简单顺序连接在大多数情况下都是错误的。你必须依据GPA导出数据中“面”的定义来构建triangles列表。这可能意味着需要解析第二个CSV文件或者理解顶点列表的隐含顺序。RecalculateNormals()自动为网格生成平滑的法线这对于Standard Shader的光照计算至关重要。mesh.indexFormat处理顶点数超过65535的高模时必须将索引格式设置为32位。5. 常见问题与排查技巧实录在实际操作中你一定会遇到各种问题。以下是我踩过坑后总结的排查清单问题现象可能原因排查与解决方案模型完全不可见1. 网格没有正确赋值给MeshFilter。2. 三角形索引顺序错误背面剔除。3. 模型尺寸太大或太小超出摄像机视锥。1. 在RenderMesh后检查meshGo的MeshFilter组件是否确实有Mesh资产。2. Unity默认背面剔除。检查三角形顶点顺序是否为顺时针从可见面看。尝试在材质Shader中关闭剔除Cull Off测试。3. 将摄像机拉远或检查生成网格的bounds。模型可见但纯黑/纯白1. 材质球问题。2. 法线计算错误。1. 临时给材质一个无贴图的Unlit/ColorShader看是否有颜色。2. 确保调用了mesh.RecalculateNormals()。也可以在Shader中使用法线贴图调试模式查看。贴图显示但严重拉伸/错乱1. UV生成算法不适合模型几何。2. UV值超出[0,1]范围Wrap Mode影响。1. 换用基于法线的多投影轴算法见3.2节心得。2. 在UV生成后遍历所有UV值确保其在0到1之间。检查材质的贴图Wrap Mode是否为Repeat或Clamp。导入后模型位置/旋转不对坐标系转换错误。在解析CSV顶点坐标时调整坐标系的转换。常见的是交换Y和Z并可能取反某一轴new Vector3(x, z, -y)或new Vector3(x, z, y)。需要根据源数据测试。性能卡顿Draw Call过高生成了大量独立的GameObject和Mesh。使用Mesh.CombineMeshes将多个小网格合并。确保合并后的网格数量尽可能少。读取CSV文件路径错误Application.streamingAssetsPath在平台间路径不同或文件不存在。使用Debug.Log打印出fullPath检查。在Unity Editor中StreamingAssets位于项目根目录下。在Android/iOS上它是只读的压缩包内路径读取方式需用UnityWebRequest或WWW。独家避坑技巧分步调试不要一次性写完所有代码。先写一个只读取CSV并打印顶点数的版本。然后写一个用简单几何如两个三角形测试UV生成的版本。最后再整合。可视化调试在OnDrawGizmos中绘制顶点和法线。对于生成的网格可以创建一个临时脚本在Update里用Debug.DrawRay从每个顶点沿法线方向画线直观检查法线方向。使用简单材质调试阶段使用Unlit/Texture或Unlit/ColorShader排除复杂光照和Shader计算的影响。处理大规模数据如果CSV文件巨大几十万顶点考虑在编辑器模式下异步生成并保存为Asset而不是在运行时加载。可以使用EditorCoroutines需导入包或后台线程配合MainThreadDispatcher。6. 工具化与扩展思路上述脚本是一个起点。你可以将其扩展成一个更强大的工具编辑器工具Editor Tool创建一个EditorWindow提供GUI来选择CSV文件、设置坐标系转换规则、选择UV生成策略并一键生成Prefab。支持更多属性CSV中可能包含顶点颜色R,G,B,A、法线Nx,Ny,Nz或第二套UV。扩展解析逻辑将这些数据也填入Meshmesh.SetColors,mesh.SetNormals,mesh.SetUVs(1, ...)。更智能的UV生成实现上文提到的按面片法向投影算法对于建筑群模型效果会好很多。集成到Asset导入管道通过实现AssetPostprocessor接口可以让你在导入.obj文件时自动检测其是否缺失UV并调用你的算法为其生成实现完全自动化的预处理。这个方案的精髓在于理解数据流和Unity网格系统的核心。一旦掌握了从原始数据到Mesh对象的构建过程你就能处理来自各种非标准渠道的模型数据而不仅仅是GPA。无论是从点云数据、自定义二进制格式还是网络API获取的几何信息你都能将它们无缝地呈现在Unity的舞台上。

相关新闻

PixVerse视频生成模型:本地部署、API集成与批量任务实战对比

PixVerse视频生成模型:本地部署、API集成与批量任务实战对比

这次我们来看一个关于视频生成领域的有趣话题——PixVerse与其他新兴视频生成模型的对比分析。随着AI视频生成技术的快速发展,各种模型在生成质量、硬件要求和使用便捷性上展现出明显差异。本文将重点分析PixVerse的核心特点,并与其他主流视频生成工具进…

2026/10/10 17:21:38 阅读更多 →
补天平台漏洞提交实战指南:从报告撰写到审核沟通的避坑技巧

补天平台漏洞提交实战指南:从报告撰写到审核沟通的避坑技巧

1. 项目概述:为什么你需要这份实战指南在安全圈子里混了这么多年,我见过太多新手白帽子,怀揣着技术热情和对漏洞挖掘的憧憬,一头扎进补天漏洞响应平台,结果却因为提交不规范、沟通不畅或者对规则理解不透彻&#xff0c…

2026/10/13 23:22:50 阅读更多 →
Anthropic技术路线调整对开发者的影响与应对策略

Anthropic技术路线调整对开发者的影响与应对策略

最近AI圈有个很有意思的现象:当大家都在关注GPT-5什么时候发布时,Anthropic内部却在上演一场"兄弟阋墙"的戏码。根据多方消息,原本计划中的Fable 5项目似乎被内部代号为Opus 5的新模型"截胡"了,这直接导致了A…

2026/10/13 15:45:50 阅读更多 →

最新新闻

C#调用WebService获取PDF转图片:选型与踩坑实战

C#调用WebService获取PDF转图片:选型与踩坑实战

做C#开发这几年,遇到“调用WebService获取PDF文件再转换为图片”这种需求不算少。可能是一个审批系统需要预览合同,也可能是一个报表平台需要把服务端生成的文件转成缩略图展示。总之核心工作就两件事:把远程文件拿下来,再在本地转…

2026/10/14 6:40:29 阅读更多 →
Unity Spark实战:在浏览器中用AI自然语言快速做游戏原型

Unity Spark实战:在浏览器中用AI自然语言快速做游戏原型

看到“Unity Spark 正式发布”这条消息的时候,我第一反应是:又来了。这年头但凡和 AI 沾边的工具都在喊“原生支持 AI”,口号早就被用烂了。但等我真正在浏览器里打开这个基于 AI 的游戏开发环境,亲手生成一个场景、跑通一次跳跃、…

2026/10/14 6:40:29 阅读更多 →
仓颉语言属性(prop)完全指南:getter/setter 定义、抽象属性与继承覆盖实战

仓颉语言属性(prop)完全指南:getter/setter 定义、抽象属性与继承覆盖实战

文档编程语言 【免费下载链接】cangjie_docs 仓颉编程语言开发者文档。 项目地址: https://gitcode.com/Cangjie/cangjie_docs 点击查看 免费下载 属性(Properties)是仓颉语言中用于间接获取和设置值的语言机制:它通过一个 gette…

2026/10/14 6:40:29 阅读更多 →
从Node到Bun:JavaScript运行时与工具链的工程效率革命

从Node到Bun:JavaScript运行时与工具链的工程效率革命

1. 为什么我把重心从 Node 切到了 Bun先说结论:Bun 不是又一个跑得更快的 Node,它是一整套重新设计过的 JavaScript 运行时和工具链。我最初对它的态度是观望,因为这类"下一代运行时"的宣发见过太多次了,但真正在几个中…

2026/10/14 6:40:29 阅读更多 →
C#对接WebService拉取PDF并转图片:从接口调到部署避坑

C#对接WebService拉取PDF并转图片:从接口调到部署避坑

前一阵接手一个对接任务,对方是个运行了十多年的老系统,只对外暴露SOAP风格的WebService接口。业务要求很直接:通过这个接口把PDF文件拉到我们这边,再转成图片,放到Web端做在线预览和打印存档。这类需求在C#开发里非常…

2026/10/14 6:40:29 阅读更多 →
纯Python实现猜数字游戏:从零到避坑的完整指南

纯Python实现猜数字游戏:从零到避坑的完整指南

猜数字游戏大概是很多人的第一个编程项目。它不像计算器那样枯燥,也不需要复杂的界面,但一套完整流程走下来,变量、输入输出、条件判断、循环、异常处理这些编程入门核心概念全部能练到。我最近又把这个小项目从头写了一遍,用最基…

2026/10/14 6:39:29 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/13 22:01:27 阅读更多 →
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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →