GeoJSON格式详解:从坐标系陷阱到地图可视化实战
第一次拿到 GeoJSON 数据的时候我的反应是这什么玩意儿一个打开全是花括号和数组的文本文件凭什么能变成地图上的点和面后来真上手做了一阵子地理数据处理才明白这份文件之所以能成为交换事实标准确实有它的底气。如果你正打算做地图可视化、地理位置存储或者被后端同事甩来一份 .geojson 文件不知道怎么办这篇文章就是给你写的。我会尽量把格式规则、坐标系陷阱、常用工具和排错方法揉在一起讲清楚不堆生僻术语重点放在能落地的部分。1. 为什么GeoJSON能成为默认的地理交换格式1.1 从一份打不开的地图数据说起前两年我参与一个模拟项目需要把城市里几百个采样点的分布画到页面上。后端同事最初给的是 Excel 表格两列经纬度数字一列名称看起来清清楚楚。可真到了前端地图上点位要么飞到海里要么挤成一团折腾了整整一下午。最后技术负责人受不了了让后端改用 GeoJSON 导出前端拿到文件直接渲染问题当场消失。那次经历让我意识到一件事地理数据不是简单把经纬度拿出来就能用的它需要一套双方都能理解的结构化约定。GeoJSON 就是这套约定的标准答案。它本质上是 JSON 的一个地理扩展所有内容都可以用文本编辑器打开查看也是 JavaScript 原生能直接处理的数据结构。前后端传数据、存数据库、做离线包都可以直接拿这份文件操作不需要额外定义协议。1.2 GeoJSON 的数据组织逻辑要素和几何体的层次GeoJSON 的组织方式很像我们平时填表格。一张完整的地理数据表叫做 FeatureCollection要素集合里面可以包含多个 Feature要素每一个 Feature 又有 properties属性和 geometry几何体。这里的 properties 就是普通 JSON 对象你想挂什么字段都行比如采样点编号、温度值、采集时间。而 geometry 里必须有 type 和 coordinates 两个字段type 表示几何类型coordinates 是具体的坐标数组。这种分层结构好处非常明显几何数据和业务属性数据完全解耦前端画图时只关心 geometry做筛选统计时只读 properties谁都不干扰谁。注意一点FeatureCollection 是一个容器它本身不需要坐标真正带坐标的是被它包裹的 Feature。很多初学者会混淆这个层级在 FeatureCollection 那一层硬找 coordinates结果自然是 null。1.3 一个最小可解析的 GeoJSON 长什么样写个最朴素的点要素示例你一看就懂{ type: FeatureCollection, features: [ { type: Feature, properties: { name: 采样点A, value: 23.5 }, geometry: { type: Point, coordinates: [116.4, 39.9] } } ] }这段 JSON 表示存在一个要素集合里面只有一个点要素坐标是东经 116.4 度、北纬 39.9 度。随便用一个支持 GeoJSON 的地图库加载它页面上就能出现一个标记点。规模扩大时只需要往 features 数组里继续塞要素即可几千个点、几百条路、几十个区域都遵循同一套规则。2. 几何类型拆解点线面背后的规则2.1 六种标准几何类型与嵌套关系GeoJSON 规范现在通行的版本是 RFC 7946规定了七种几何类型常用的有六种外加一种特殊的 GeometryCollection。它们其实可以分成三组Point 和 MultiPointLineString 和 MultiLineStringPolygon 和 MultiPolygon。其中 Multi 开头的类型就是把单个几何体打包成数组比如 MultiPoint 就是多个点坐标组成的数组MultiLineString 就是多条折线组成的数组。这六种类型彼此之间不能混用。比如你把一个线段的坐标数组填进 Polygon 里解析器大概率会直接报错或者把图形画成一个诡异的三角形。原因在于每种类型对坐标数组的嵌套层数有严格要求后面我会详细拆。2.2 坐标数组的层级规律与常见解析错误直接给坐标嵌套层级规律表这是排错时的核心参考几何类型coordinates 数组层级示例结构Point一层数值数组[lng, lat]MultiPoint两层数组[[lng, lat], [lng, lat]]LineString两层数组[[lng, lat], [lng, lat]]MultiLineString三层数组[[[lng, lat], [lng, lat]]]Polygon三层数组[[[lng, lat], [lng, lat], [lng, lat], ...]]MultiPolygon四层数组[[[[lng, lat], [lng, lat]]]]最常见的解析错误就是层级数搞错。有一次我拿一份区域数据做渲染前端一直画不出面报错说“invalid geometry”。打印出坐标结构后才发现数据源头在做格式转换时把一个 Polygon 的坐标数组外面多包了一层中括号变成了 MultiPolygon 级别的嵌套。地图库按照 Polygon 去解析自然失败。排查这类问题最快的办法不是盯代码而是把 JSON 打开人工数一遍中括号层数对照上表就能定位问题。2.3 多边形环绕方向与自相交限制Polygon 的坐标数组还有一个特殊规则坐标数组的第一个元素是外环后续的元素是内环也就是洞。比如一个带湖泊的多边形区域外环是陆地边界内环是湖的边界。规范建议外环使用逆时针方向内环使用顺时针方向但大多数解析器在这点上其实比较宽松正反都能画出来。真正会让你崩溃的是自相交多边形。所谓自相交就是多边形的边自己和自己交叉形成一个类似蝴蝶结形状的图形。地图引擎处理自相交的逻辑五花八门有的直接显示一个奇怪形状有的干脆拒绝渲染。所以在生成 Polygon 数据之前最好先用工具做一次拓扑校验。Python 里可以用 shapely 的is_valid方法检查前端也可以用 turf.js 的booleanValid做判断。from shapely.geometry import shape import json with open(area.geojson, encodingutf-8) as f: data json.load(f) geom shape(data[features][0][geometry]) print(多边形是否有效:, geom.is_valid)3. 坐标系约定GeoJSON 默认在 WGS84 这件事3.1 为什么必须显式注意 EPSG:4326地理数据领域最坑人的不是数据结构而是坐标系。同一串经纬度数字在不同坐标系下代表的地球位置完全不一样。GeoJSON 规范明确规定所有坐标必须使用 WGS84 坐标系也就是通常说的 EPSG:4326且不能附加自定义坐标系参数。这意味着如果你的原始数据是投影坐标系比如常见的 Web Mercator即 EPSG:3857那么必须先转成 WGS84 经纬度再写成 GeoJSON。否则前端地图加载出来以后点位会偏移到完全不可用的位置而且这种偏移是肉眼难以发现但量级很大的系统性错误。我见过一个典型翻车案例某团队把 UTM 投影坐标的数据当成经纬度直接填进了 GeoJSON渲染出来的点位与真实位置差了上百公里地图缩放到城市级别时点位直接落在邻近城市。事后排查花了两天才发现是数据源没有做坐标系转换。3.2 经纬度顺序可怜的地理爱好者的经典翻车现场GeoJSON 里坐标数组的第一个元素必须是经度第二个是纬度也就是 [lng, lat]对应数学上的 [x, y]。但很多人日常写顺手了会习惯写成 [lat, lng]第一个写纬度第二个写经度。这个顺序问题在外行看来只是先后顺序的区别实际效果却非常严重。因为纬度的数值范围是 -90 到 90经度范围是 -180 到 180把二者互换之后点位可能从中国被甩到太平洋甚至南美洲。更隐蔽的是如果经纬度数值恰好都比较小互换之后点位偏差可能只有几十公里比例尺大时根本看不出问题一旦缩小地图就会发现位置明显不对。强烈建议凡是和 GeoJSON 打交道一律按照“先经后纬”写坐标。前端 Leaflet 用的是 [lat, lng]正好和 GeoJSON 相反这也是大量新手混淆的根源。3.3 高精度坐标与浮点舍入问题坐标数值的精度同样值得留意。WGS84 坐标系里纬度方向每 0.000001 度大约对应 0.11 米经度方向在赤道上类似但高纬度地区会有偏差。理论上保留六位小数就能满足绝大多数民用场景的精度需求。然而如果你直接从 GPS 设备或者某些 API 拿数据原始经纬度可能带着十几位小数。这些多出来的尾数在存储和传输中没有任何实际意义反而会带来两个问题一是文件体积增大二是某些解析器在浮点数精度处理上表现不佳可能导致坐标值发生微小的异常变动。我在实际项目中会统一把经纬度保留到六位小数用 Python 处理时写一个简单的小工具自动截断def trim_coords(coords, digits6): if isinstance(coords, (int, float)): return round(coords, digits) if isinstance(coords, list): return [trim_coords(c, digits) for c in coords] return coords这个递归函数能处理任意嵌套层级的坐标数组把浮点数统一截断到指定小数位。虽然看起来是小事但对文件体积和后续空间计算的稳定性都有实际帮助。4. 实际场景应用从渲染到空间计算的完整链路4.1 前端地图快速渲染的最小实现GeoJSON 在前端渲染通常配合 Leaflet 或 MapLibre GL 这类开源地图库使用。以 Leaflet 为例读取一份 GeoJSON 并渲染成点和多边形核心代码只有几十行fetch(data.geojson) .then(response response.json()) .then(data { L.geoJSON(data, { pointToLayer: (feature, latlng) { return L.circleMarker(latlng, { radius: 5 }); }, style: (feature) ({ color: feature.properties.value 30 ? #d73027 : #1a9850 }), onEachFeature: (feature, layer) { layer.bindPopup(名称: ${feature.properties.name}); } }).addTo(map); });这里有一个关键点Leaflet 内部虽然使用 [lat, lng] 顺序但 L.geoJSON 方法会自动处理 GeoJSON 的 [lng, lat] 坐标顺序转换你不需要手动倒转坐标数组。如果手动遍历 coordinates 自己创建 marker就要小心顺序问题了。4.2 用 Python 处理 GeoJSON 的常用套路服务端处理 GeoJSON 更关注数据清洗、格式转换和空间计算。我用得最多的组合是 geopandas 加上 shapely。geopandas 可以直接读取 GeoJSON 文件为 DataFrame 结构筛选、聚合、导出都非常顺手。import geopandas as gpd gdf gpd.read_file(data.geojson) print(gdf.crs) # 查看坐标系信息 gdf_subset gdf[gdf[value] 100] gdf_subset.to_file(filtered.geojson, driverGeoJSON)这里要特别说一下crs参数。geopandas 读取 GeoJSON 时会自动将坐标系标记为 EPSG:4326但如果原始文件本身的坐标不是 WGS84读取出来的 GDF 也会带着错误的坐标系标记。处理这类数据前最好先打印 crs 确认如果源数据是其他坐标系先用to_crs(epsg4326)转换再落盘。4.3 GeoJSON 在空间计算与服务端存储中的角色除了渲染展示GeoJSON 还常常作为空间计算的数据交换格式。比如利用 shapely 判断某个点是否落在某个区域内、计算两个多边形的交集面积、计算点与线的最短距离。这些计算不需要可视化但底层读取的仍然是 GeoJSON 结构。在服务端存储方面主流关系型数据库都提供了对 GeoJSON 的良好支持。比如 PostgreSQL 的 PostGIS 扩展可以直接把 GeoJSON 字符串转成几何对象存入数据库空间索引、范围查询、距离排序都原生支持。转换过程大致是把 GeoJSON 的 geometry 部分提取出来调用 ST_GeomFromGeoJSON 方法写入查询后也可以用 ST_AsGeoJSON 把结果转回 GeoJSON 输出给前端。这套链路在现代 GIS 应用里相当成熟岗位需求也一直很稳定。5. 同类格式横向对比何时不选 GeoJSON5.1 常见地理数据格式的差异GeoJSON 并非万能实际工作中还有一些常见的地理数据格式各有各的适用场景。我做过一个横向对比整理成表格对比项GeoJSONKMLShapefileWKT本质JSON 文本XML 文本二进制多文件纯文本定义可读性高中等低高体积较大较大较小最小属性支持完整完整有限制无主流支持极广一般成熟但老旧数据库内常见典型场景Web 前端Google 地图生态传统 GIS 软件空间数据库交换如果你面向 Web 应用GeoJSON 几乎是首选。如果和传统 GIS 软件如某桌面端 GIS 工具打交道Shapefile 仍然是绕不开的格式但它不是单文件而是由至少三个文件组成存放几何的.shp、存放属性的.dbf、存放索引的.shx缺少任何一个文件都无法正常打开传输时很容易漏文件。5.2 TopoJSON 与精简曲线TopoJSON 是 GeoJSON 的一种紧凑变体它的核心思路是复用共享的线段。举个例子两个相邻县的边界在 GeoJSON 里会被重复存储两次一条边界的坐标出现在两个多边形里而 TopoJSON 把公共边界只存一次通过引用来组装各个多边形。这种去重策略在处理高精度行政区划数据时效果极其明显文件体积能缩小到原来的十分之一甚至更低。TopoJSON 还支持量化简化比如保留坐标小数点后三位用来满足不同缩放级别下的显示需求。但代价是TopoJSON 不能被地图库直接渲染必须先经过 topojson-client 这类库把数据转换回 GeoJSON。因此它更适合作为传输和存储格式渲染前再解包。5.3 体积大户的应对策略简化与 MBTiles 思路GeoJSON 最大的软肋是文件体积。因为每个几何体的坐标都以明文数字形式存储坐标点越多体积越大。一份包含全国道路网明细的 GeoJSON 可能达到几百 MB浏览器直接加载必然卡死。应对策略通常有三种。第一是几何简化用算法减少坐标点数比如 shapely 的simplify方法通过容差参数控制简化程度。第二是空间分块把大区域按网格切分成多个小文件前端按需加载类似地图瓦片的思想。第三是用 MBTiles 这种 SQLite 格式做离线数据包它内部可以存储大量的矢量瓦片数据地图引擎直接读取性能和体验都比直接解析巨型 GeoJSON 好很多。6. 踩坑总结与调试方法论6.1 解析失败时的系统性排查顺序GeoJSON 解析失败或者渲染异常时我建议按照固定顺序排查效率最高先用 JSON 语法校验工具检查文件本身是不是合法 JSON。任何多一个逗号、少一个括号的问题都会导致整体解析失败。检查坐标数组的嵌套层级是否符合几何类型要求对照第二节的表格逐层核对。检查坐标值范围经度必须在 -180 到 180 之间纬度必须在 -90 到 90 之间。超过这个范围大概率是坐标系错误。检查经纬度顺序确认第一位是经度第二位是纬度。检查要素的外环闭合性。Polygon 的外环首尾坐标必须相同否则图形无法闭合。这五步基本覆盖了我遇到过的九成问题。剩下的一成多是数据中混入了非法字符、文件编码不对、或者字段类型不符合预期。6.2 验证工具与手写代码自查排查过程中验证工具能帮上大忙。我最常用的是 GeoJSONLint 这类在线验证服务直接把 JSON 文本粘贴进去它会把语法错误和结构错误一起提示出来。后端处理时也可以用 shapely 的is_valid做几何有效性检查用 geopandas 的read_file做读取测试。只要这几个环节都过了数据基本就能放心交给地图渲染。如果遇到不常见的错误手写一段排查代码往往比工具更可靠。比如遍历所有要素逐个解析 geometry 类型和坐标系范围def validate_geojson(path): import json with open(path, encodingutf-8) as f: data json.load(f) for idx, feat in enumerate(data[features]): geom feat[geometry] coords geom[coordinates] if geom[type] Polygon: if len(coords[0]) 4: print(f要素 {idx}: 外环坐标不足4个未闭合) if coords[0][0] ! coords[0][-1]: print(f要素 {idx}: 外环未闭合) # 递归检查经纬度范围 def check(c): if isinstance(c, list): for x in c: check(x) elif isinstance(c, float): pass check(coords)实际使用时可以按需要补充更多规则这套思路比看一眼报错盲猜要扎实得多。6.3 我平时写 GeoJSON 的一点习惯顺手分享几个日常养成的习惯算不上什么高深技巧但能避免很多不必要的返工。第一所有坐标统一先经后纬写进代码注释里防止换人维护时被改成错误顺序。第二属性字段名全部使用英文加下划线避免中文键名在不同编码环境下的兼容性问题。第三经手较大的 GeoJSON 文件时永远先写一版小体积的样例数据测试渲染效果确认样式和交互逻辑没问题后再上全量数据。第四保留一份数据生成脚本而不是只保留最终文件因为上游数据更新后重新生成总比手工改文件靠谱。做地理数据这行真正的门槛不在 API 调用而在数据本身的质量。GeoJSON 规范本身不算复杂但它作为数据交换的入口串联起了前端展示、后端存储、空间计算整条链路。把格式规则、坐标系约定和常见坑摸透后续遇到什么样的地理数据项目都能很快走上正轨。如果这份文件格式让你头疼过希望这篇文章能帮你少走几个弯路。

相关新闻

小程序日期格式化:iOS NaN问题解析与通用Util封装实践

小程序日期格式化:iOS NaN问题解析与通用Util封装实践

如果你在小程序里写过日期格式化,大概率碰到过这个场景:代码在开发者工具里跑得好好的,Android 真机上也正常,一拿到 iOS 上预览,界面直接给你一排NaN-NaN-NaN NaN:NaN:NaN。我第一次遇到这问题是在某次项目评审前的自…

2026/10/17 15:05:33 阅读更多 →
JDBC核心操作全解析:从MySQL连接、建表到PreparedStatement防注入实战

JDBC核心操作全解析:从MySQL连接、建表到PreparedStatement防注入实战

1. 从一个真实踩坑场景说起:为什么JDBC这些基础值得反复梳理 刚入行那会儿,我接手过一个内部数据管理模块,需求很简单:连上数据库,建几张表,做增删改查。当时觉得这玩意儿能有多难,照着教程抄一…

2026/10/18 2:13:42 阅读更多 →
C语言位域实战:从内存优化到协议解析的完整指南

C语言位域实战:从内存优化到协议解析的完整指南

简介:一份以位域(bit field)代码为核心的完整工程资料包,面向C/C初学者与中级开发者,也适用于在ROS/catkin环境中集成自定义结构体的工程师。压缩包共16个文件,既有核心的C头文件与源文件,也包含…

2026/10/16 11:23:48 阅读更多 →

最新新闻

2026年AI接口聚合服务深度横评:从调用稳定性看词元之河与硅基流动的中小团队适配度

2026年AI接口聚合服务深度横评:从调用稳定性看词元之河与硅基流动的中小团队适配度

2026年5月完成的一轮 AI 接口聚合服务实测横评,方法论为 72 小时连续压测、12 类典型调用场景模拟与 37 位一线开发者访谈。行业背景值得关注:据《中国AI基础设施白皮书(2026Q1)》,超过 68% 的中小技术团队在大模型应用…

2026/10/18 2:12:56 阅读更多 →
手工LL(1)编译器实战:从词法到语义的5层避坑指南

手工LL(1)编译器实战:从词法到语义的5层避坑指南

简介:本资源是一份完整的高校编译原理课程设计报告,面向计算机专业本科生及编译技术初学者,聚焦Pascal子集编译器的系统性实现与原理剖析。报告涵盖词法分析(含符号表构建与注释处理)、语法分析(自顶向下LL…

2026/10/18 2:12:56 阅读更多 →
香港公司注册怎么办理?

香港公司注册怎么办理?

一、香港公司注册是什么?有什么用? 香港公司注册,是指依据香港《公司条例》,向香港公司注册处提交申请,取得公司注册证书及商业登记证的法律程序。 对跨境卖家、外贸企业和品牌方而言,香港公司主要用于&…

2026/10/18 2:12:56 阅读更多 →
阿里钉钉Java集成实战:组织同步、消息推送与审批回调全链路落地

阿里钉钉Java集成实战:组织同步、消息推送与审批回调全链路落地

简介:本资源是一套面向Java开发者的企业级钉钉集成实战项目,聚焦阿里钉钉开放平台API在业务系统中的落地应用,适用于需实现组织通讯、审批流对接、消息推送及移动办公集成的中高级后端工程师。压缩包共174个文件,含32个核心Java源…

2026/10/18 2:12:56 阅读更多 →
力扣排序题复盘:核心模板、比较器陷阱与高效刷题路线

力扣排序题复盘:核心模板、比较器陷阱与高效刷题路线

说起力扣刷题,排序题目是我最早碰、也最晚想明白的一类。刚开始我以为"过一遍快排和归并就能应付",结果连续几道题把我按在地上摩擦——不是不会写排序,而是不知道题目想让我用什么排序、为什么这么排序、边界条件又藏在哪里。这篇…

2026/10/18 2:12:56 阅读更多 →
BLE OTA断连恢复设计:从参数配置到双Bank兜底的全流程指南

BLE OTA断连恢复设计:从参数配置到双Bank兜底的全流程指南

/* 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 2:11:56 阅读更多 →

日新闻

基于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/16 14:23:36 阅读更多 →