VOC2012行人数据抽取与YOLOv3单类检测器训练实战
1. 从VOC2012里捞出行人为什么值得单独训一个检测器行人检测这件事看起来像是通用目标检测的一个子集很多人第一反应是我直接拿COCO预训练的YOLOv3跑不就行了。我一开始也是这么想的直到在实际场景里被现实教育了几次。通用模型对人这个类别的定义太宽泛了——坐着的人、被遮挡一半的人、远处只有几十个像素的人、海报上印的人它都可能给你框出来而且框的置信度还不低。如果你下游要做的是客流统计、区域入侵判断、或者视频摘要里的人物轨迹提取这种什么都算人的召回反而成了负担。VOC2012这个数据集在行人检测里是个很微妙的存在。它不像COCO那样把person类别做得那么全也不像Caltech、CityPersons那样专门针对行人做了密集标注。VOC2012的person类别标注相对干净主要覆盖的是站立、行走、骑行等姿态比较明确的个体而且图像分辨率普遍不高大多在500×375上下这反而和很多实际部署场景比如720P监控截图、手机拍摄的街景的尺度分布比较接近。所以从VOC2012里把person类抽出来单独训一个YOLOv3得到的模型在标准姿态行人上的精度往往比通用COCO模型更可控误检也更容易压下去。这篇文章我想聊的就是这条路径的完整落地过程怎么从VOC2012的XML标注里把行人数据抽干净、怎么转成YOLOv3要的格式、配置文件怎么改、训练时哪些参数是坑、以及训完之后怎么判断这个模型到底能不能用。适合已经跑通过YOLOv3官方demo、想进一步做垂直类别定制的朋友。如果你连Darknet都还没编译过建议先把官方仓库的README走一遍再回来不然中间很多报错会让人抓狂。需要先说明一点下面所有涉及路径、文件名的地方我都会用通用写法你按自己的目录结构替换即可。数据集我也不会贴具体下载链接VOC2012的获取方式很成熟自己搜一下就能找到。2. 把VOC2012的标注拆开行人数据的抽取逻辑2.1 VOC的XML结构决定了抽取方式VOC2012的标注是每张图一个XML文件放在Annotations目录下图像放在JPEGImages。一个典型的XML长这样annotation filename2008_000008.jpg/filename size width500/width height375/height depth3/depth /size object nameperson/name bndbox xmin174/xmin ymin101/ymin xmax349/xmax ymax351/ymax /bndbox difficult0/difficult /object ... /annotation抽取的核心逻辑就三步遍历所有XML找出所有name为person的object把对应的bndbox记下来如果一张图里有多个person就记多行如果一张图里一个person都没有这张图直接丢弃。听起来简单但真正动手时你会发现几个必须处理的细节。第一个细节是difficult字段。VOC里标了difficult1的目标通常是被严重遮挡、或者小到人眼都难辨认的实例。训练时如果把它们当正样本模型会学到一堆噪声如果当负样本又会让模型对遮挡行人过度保守。我的做法是抽取阶段保留difficult标记但在生成训练列表时把difficult1的框过滤掉同时如果一张图过滤后一个person都不剩这张图也不进训练集。这样能保证训练样本的干净度。第二个细节是坐标越界。VOC的标注偶尔会出现xmax超过图像宽度、或者xmin为负数的情况标注员手抖。YOLOv3在计算loss时如果遇到越界框IoU计算会出问题轻则loss异常重则直接NaN。所以抽取时一定要做一次clamp把坐标限制在[0, width]和[0, height]范围内并且过滤掉宽或高小于3像素的框——这种框转成YOLO格式后基本就是一条线没有训练价值。2.2 抽取脚本的写法与踩坑我用Python写抽取脚本依赖xml.etree.ElementTree就够了不需要装额外的解析库。核心结构大概是这样import os import xml.etree.ElementTree as ET def extract_person(anno_dir, img_dir, out_list): records [] for xml_file in os.listdir(anno_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(anno_dir, xml_file)) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) img_name root.find(filename).text boxes [] for obj in root.findall(object): name obj.find(name).text if name ! person: continue difficult obj.find(difficult) if difficult is not None and int(difficult.text) 1: continue bbox obj.find(bndbox) xmin max(0, int(float(bbox.find(xmin).text))) ymin max(0, int(float(bbox.find(ymin).text))) xmax min(w, int(float(bbox.find(xmax).text))) ymax min(h, int(float(bbox.find(ymax).text))) if xmax - xmin 3 or ymax - ymin 3: continue boxes.append((xmin, ymin, xmax, ymax)) if boxes: records.append((img_name, w, h, boxes)) return records这里有个容易忽略的点VOC的坐标有时候是浮点字符串比如174.0直接int()会报错所以要先float()再int()。我第一次跑的时候就因为这个卡了半小时报错信息还特别不直观。抽完之后VOC2012的person实例大概在几千到一万出头这个量级具体数字取决于你是否过滤difficult。这个量级对YOLOv3来说偏少所以后面必须靠数据增强来撑这一点我在第4节会展开。2.3 训练集/验证集的划分策略划分不能简单随机。VOC2012的图像本身有场景聚集性——同一个场景可能有多张连续拍摄的图。如果随机划分训练集和验证集里会出现高度相似的图验证指标会虚高。我的做法是按filename的前缀VOC的文件名格式是年份_编号做分组同一组只进一个集合然后按8:2划分。这样验证集更能反映模型在没见过场景上的表现。另外验证集里我建议保留一部分difficult1的样本但评估时单独统计。这样你能看到模型对遮挡行人的真实能力而不是被过滤后的漂亮指标骗了。3. 转成YOLO格式坐标归一化与列表生成3.1 YOLO格式的本质YOLOv3要的标注格式是每张图一个.txt每行一个目标格式为class_id center_x center_y width height其中后四个值都是相对于图像宽高的归一化值范围[0,1]。因为我们只做person一个类class_id恒为0。这里有个新手常犯的错误以为width和height是像素值。不是是归一化后的比例。比如一个框宽100像素、图宽500像素那width0.2。转换公式center_x (xmin xmax) / 2.0 / img_w center_y (ymin ymax) / 2.0 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h3.2 生成train.txt和val.txtYOLOv3训练时需要两个列表文件每行是一张图的绝对路径。注意是绝对路径相对路径在Darknet里经常出问题。生成逻辑def write_list(records, img_dir, list_path): with open(list_path, w) as f: for img_name, w, h, boxes in records: img_path os.path.abspath(os.path.join(img_dir, img_name)) f.write(img_path \n) label_path img_path.replace(JPEGImages, labels).replace(.jpg, .txt) with open(label_path, w) as lf: for (xmin, ymin, xmax, ymax) in boxes: cx (xmin xmax) / 2.0 / w cy (ymin ymax) / 2.0 / h bw (xmax - xmin) / 1.0 / w bh (ymax - ymin) / 1.0 / h lf.write(f0 {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}\n)这里我建议把label文件放在和图像平行的labels目录下而不是混在JPEGImages里。原因很简单Darknet在训练时会去读图像同目录下的同名.txt如果你把label和图像放一起JPEGImages目录会变得很乱而且做数据增强、复制文件时容易漏掉label。分开存放路径映射清晰后期排查也方便。3.3 一个必须检查的环节label与图像的一一对应转完之后一定要写个校验脚本检查三件事train.txt里每张图是否存在、每张图对应的label文件是否存在、label文件里每行的数值是否都在[0,1]范围内。我见过太多人训练loss一直不降最后发现是某几张图的label路径写错了Darknet读不到label就当成这张图没有目标来训等于往模型里灌负样本。校验脚本很简单遍历一遍把异常的行打印出来。这个五分钟的检查能省你几个小时的debug。4. 配置文件改造从cfg到data的完整清单4.1 创建person.data和person.namesDarknet的训练入口是.data文件内容大概这样classes 1 train /path/to/train.txt valid /path/to/val.txt names /path/to/person.names backup /path/to/backupperson.names里就一行person。classes1这个值必须和后面cfg里的classes以及filters严格对应错一个就报维度不匹配。4.2 修改yolov3.cfg的三个yolo层和前面的conv层YOLOv3的cfg里有三个[yolo]层分别对应三个尺度的输出。每个[yolo]层上面紧挨着一个[convolutional]层那个conv层的filters值需要改。公式是filters (classes 5) * 3单类时filters (1 5) * 3 18。原版是(805)*3255所以你要把三个filters255都改成filters18。同时每个[yolo]层里的classes80改成classes1。这里有个坑cfg里filters出现多次除了yolo层前面的conv其他地方也有conv层带filters。你只能改紧挨着[yolo]的那三个改错了整个网络结构就崩了。建议用搜索定位[yolo]然后往上找最近的[convolutional]。4.3 关于预训练权重的取舍官方提供了darknet53.conv.74这个预训练权重它只包含卷积层不含检测头。用它是标准做法能让模型在几千张图上也能收敛。但如果你直接用COCO训好的yolov3.weights去finetune会遇到一个问题COCO的检测头是80类你的新头是1类层结构对不上Darknet加载时会跳过不匹配的层实际上等于只用了backbone。所以直接用darknet53.conv.74更干净不用纠结。4.4 训练命令与关键参数./darknet detector train person.data yolov3-person.cfg darknet53.conv.74 -gpus 0几个我实际调过的参数burn_in1000前1000次迭代用较低学习率预热防止一开始梯度爆炸。max_batches单类几千张图我一般设到20000左右。设太大过拟合设太小欠拟合。steps16000,18000在max_batches的80%和90%处降学习率。learning_rate0.001比原版80类的0.001略保守因为数据量小。如果显存不够把cfg里[net]下的width和height从416降到320batch从64降到16或8。单类任务对分辨率没那么敏感320往往够用。5. 数据增强几千张图怎么撑起一个检测器5.1 YOLOv3自带的增强够不够Darknet的cfg里[net]段有angle、saturation、exposure、hue这些增强参数。默认值比较温和。对行人数据我建议把angle设到±10度左右——行人本身有直立性旋转太大会产生不自然的姿态。saturation和exposure可以适当调大模拟不同光照。hue对行人检测帮助有限保持默认即可。但光靠这些不够。VOC2012的person实例偏少模型很容易记住训练集的背景。我的补充做法是离线增强对训练集里的每张图随机做水平翻转、随机裁剪裁剪后如果person框还在就保留把数据量扩到原来的3到4倍。注意水平翻转对行人完全安全不像交通标志那样有方向语义。5.2 mosaic增强的取舍YOLOv4之后mosaic增强很流行把四张图拼成一张。它对小目标检测提升明显但对行人有个副作用拼接边界处可能出现半个人模型会学到一些奇怪的截断特征。如果你下游场景里行人都是完整的mosaic要慎用如果场景里遮挡、截断很常见那mosaic反而有帮助。我的建议是先不用mosaic训一版看验证集表现如果小目标召回差再加。5.3 负样本的补充行人检测最烦的误检来源是像人的东西——消防栓、邮筒、某些雕塑、甚至衣服模特。VOC2012里这类负样本不多。我的做法是从VOC里把不含person的图也抽一部分出来作为纯负样本加入训练列表label文件为空。比例控制在正样本图的20%左右。这样模型对背景的判别会更稳。注意纯负样本的label文件要存在但为空不能没有否则Darknet会报错。6. 训练过程中的异常信号与排查链路6.1 loss曲线的正常形态YOLOv3的loss是多项之和box、obj、clsDarknet打印的avg loss是滑动平均。正常情况前几百次迭代loss从大几百快速降到几十然后缓慢下降到一万次左右进入个位数到十几的区间震荡。如果loss一直卡在几百不降八成是数据或配置问题不是模型问题。6.2 我遇到过的三类典型故障第一类loss直接NaN。原因通常是学习率太大或者标注里有越界框。排查顺序是先检查label文件里有没有大于1或小于0的值再检查cfg里的learning_rate。我遇到过一次是某张图的xmax等于图像宽度归一化后正好是1.0理论上没问题但Darknet内部计算时浮点误差导致略大于1就炸了。解决办法是归一化后统一clamp到[0.001, 0.999]。第二类loss降但mAP不涨。这通常是过拟合。看训练集loss和验证集loss的差距如果训练集loss很低但验证集很高就是过拟合。对策是加增强、加负样本、或者减小模型把cfg里的通道数砍一砍。单类任务其实不需要YOLOv3那么大的容量用YOLOv3-tiny往往效果差不多还快。第三类训练中途loss突然跳高。检查是不是steps设置导致学习率降了之后又因为某种原因恢复。Darknet的学习率是按迭代数阶梯下降的不会自己恢复。如果跳高多半是某批数据有问题比如某张图损坏读不出来。可以在训练日志里找跳高那次的迭代号反推是哪张图。6.3 验证时机的选择Darknet每valid_interval次迭代跑一次验证默认在cfg里设。我建议设成每500次验证一次太频繁浪费时间太稀疏看不到趋势。验证时看的是mean average precision单类就是AP。AP在0.7以上基本可用0.8以上算不错。但别只看AP还要看recall——行人检测里漏检往往比误检更致命。7. 推理与后处理让模型输出真正能用的结果7.1 命令行推理与阈值调整./darknet detector test person.data yolov3-person.cfg backup/yolov3-person_final.weights test.jpg -thresh 0.5-thresh是置信度阈值。默认0.25对行人检测偏低会框出一堆背景。我一般从0.5起调看实际效果。如果漏检多就降到0.4误检多就升到0.6。这个值没有标准答案取决于你的场景对漏检和误检的容忍度。7.2 NMS的IoU阈值YOLOv3默认NMS的IoU阈值是0.45。行人密集场景比如地铁口里两个人挨得近框的IoU可能超过0.45导致其中一个被抑制掉。这时候要把阈值调高到0.5甚至0.6。但调太高又会出现同一个人的重复框。我的经验是如果场景里行人平均间距大于一个人宽0.45够用如果经常有并排走的情况调到0.55。7.3 输出结果的解析Darknet的detector test会输出一个predictions.jpg但如果你要集成到自己的程序里需要用detector的API或者解析输出文本。输出格式是每行类别 置信度 xmin ymin xmax ymax像素坐标。注意这里的坐标是相对于原图的不是归一化的。如果你在推理前resize了图像要按比例映射回去。8. 模型到底能不能用一套务实的评估方法8.1 别只看AP要看场景指标AP是个综合指标但实际业务里你关心的是具体场景下的表现。我习惯做三件事第一从验证集里挑出所有小目标框面积小于图像面积1%的单独算AP看模型对小行人的能力第二挑出所有遮挡样本difficult1的单独算recall第三找一批模型没见过的场景图比如不同摄像头角度人工看误检和漏检。8.2 一个容易被忽略的指标框的稳定性视频场景里如果模型对同一个行人在连续帧上的框忽大忽小下游跟踪算法会很难受。评估时可以抽一段视频看框的抖动程度。如果抖动大说明模型对尺度变化的鲁棒性不够需要加尺度增强或者用更大的输入分辨率。8.3 什么时候该考虑换方案如果你发现单类YOLOv3在验证集上AP怎么调都上不去0.7先别急着换模型。检查三件事数据量是不是真的太少少于3000个实例基本没戏、标注质量是不是有问题抽几十张图人工核对、输入分辨率是不是太低320对远距离行人确实不够。这三件事排除了再考虑换YOLOv4/v5或者用专门的行人检测框架。很多时候问题不在模型在数据。9. 一些实操下来觉得值得记下的细节训练到后期我习惯把backup目录里的权重按迭代号存一份别只留final。因为final不一定是最优的有时候15000次的权重比20000次的好。Darknet默认每100次存一次_10000.weights这种命名保留几个关键节点就行。另外如果你打算把这个模型部署到边缘设备训练时就把输入分辨率定成部署时的分辨率。比如部署用320训练就用320别用416训完再降精度会掉一截。这个坑我在一个项目里踩过重新训了一版才补回来。最后VOC2012的person标注里骑自行车和骑摩托车的人也算person但框通常只框人不框车。如果你的场景里需要区分骑车的人和走路的人单类模型做不到得加类别或者用姿态估计辅助。这是单类行人检测的固有边界提前想清楚别到部署了才发现需求对不上。

相关新闻

数据库课程设计图书馆管理系统:ER图、建表与SQL事务实战

数据库课程设计图书馆管理系统:ER图、建表与SQL事务实战

简介:这是一份面向计算机、信息管理等专业学生的《数据库系统原理》课程设计参考文档,完整呈现图书馆管理系统的设计流程。文档从课程设计目的与项目背景切入,结合高校图书馆信息化管理趋势,依次完成可行性研究、需求分析、概要设…

2026/10/13 17:00:53 阅读更多 →
Vibe Coding实战:用自然语言驱动AI编程助手生成代码

Vibe Coding实战:用自然语言驱动AI编程助手生成代码

开头Vibe Coding 这个词,过去大半年在开发者圈子里几乎每个月都要被翻出来讨论一轮。它的字面意思很好懂:用自然语言描述需求,让 AI 把代码写出来。听起来像是"动动嘴就有人帮你干活",但真正上手之后你会发现&#xff0…

2026/10/13 17:00:53 阅读更多 →
基于MCU的PS/2键盘模拟程序:从协议时序到按键注入的完整实现与避坑指南

基于MCU的PS/2键盘模拟程序:从协议时序到按键注入的完整实现与避坑指南

简介:面向电子技术、嵌入式系统开发者的PS/2键盘模拟程序源码,可让单片机仿真PS/2键盘协议、向计算机发送标准键码序列,适用于自制输入设备、自动化测试工装及特殊操作终端等场景。压缩包虽小但五脏俱全,共3个文件、整体约2KB&…

2026/10/13 17:00:53 阅读更多 →

最新新闻

fiji-win64 安装、宏脚本与插件管理:ImageJ 生物图像分析实战指南

fiji-win64 安装、宏脚本与插件管理:ImageJ 生物图像分析实战指南

简介:Fiji(ImageJ)是一个面向 Windows 六十四位系统的免安装图像处理软件,专门服务于科研和医学图像分析用户。解压后不需要安装即可运行,能够直接读取 Raw 格式原始数据,对八位以上的高动态范围图像支持良…

2026/10/13 17:32:45 阅读更多 →
DeepSeek V4.1 Flash:低延迟大模型推理引擎实战解析

DeepSeek V4.1 Flash:低延迟大模型推理引擎实战解析

1. 项目概述:这不是一次常规升级,而是一次“响应速度革命”最近在多个技术社区和开发者群聊里,几乎每天都能刷到类似这样的消息:“DeepSeek V4.1 Flash 内测开了”“Flash 版推理延迟压到 87ms”“实测比上一代 V4 Pro 在长文本场…

2026/10/13 17:32:45 阅读更多 →
SpringBoot多数据源读写分离实战:从配置到高可用路由

SpringBoot多数据源读写分离实战:从配置到高可用路由

1. 为什么多数据源不是“加个配置就行”的事——从一次线上慢查询告警说起“SpringBoot配置多数据源”这个标题,听起来像教科书里的一个练习题:改几行yml,贴几段代码,跑通就完事。但我在某电商中台项目里连续踩了三个月的坑之后才…

2026/10/13 17:32:45 阅读更多 →
DeepSeek V4.1 Flash工程解析:低延迟、省显存、长上下文稳态落地

DeepSeek V4.1 Flash工程解析:低延迟、省显存、长上下文稳态落地

1. 项目概述:一场模型性能与工程落地的双重验证 “DeepSeek V4.1 Flash”这个名称一出现,我就立刻在几个主流AI模型评测平台翻了三遍日志——不是因为名字有多炫,而是它在OpenRouter实时排行榜上连续72小时稳居Top 1,且综合得分比…

2026/10/13 17:32:45 阅读更多 →
Django插画鲜花商城系统:从电商设计到全栈实现

Django插画鲜花商城系统:从电商设计到全栈实现

插画鲜花商城系统,听名字就能猜个大概——用户端是一个走插画视觉风格的花店商城,可以浏览花束、下单买花;管理端是常规的商品、订单、用户管理。这类项目在Django毕设里属于典型的"全栈电商平台"型题目,覆盖了用户认证…

2026/10/13 17:32:45 阅读更多 →
Spring Boot汽车销售服务管理系统:从数据库设计到前后端部署全解析

Spring Boot汽车销售服务管理系统:从数据库设计到前后端部署全解析

最近有不少同学在挑毕业设计题目,我的建议是别一上来就找那种花里胡哨的“人工智能区块链”标题,先问问自己:这系统我能不能完整讲清楚、能不能真正跑起来。汽车销售服务管理系统就是这么个经典选题——业务脉络清晰,技术栈主流&a…

2026/10/13 17:31:43 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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 阅读更多 →