射频谱图目标检测:YOLOv9适配单通道时频图像实战指南
简介本资源是面向无人机无线电监管、频谱感知与智能识别领域的实战型数据集适用于计算机视觉算法工程师、信号处理研究者及AI安全方向学习者用于训练和验证无人机射频信号图像化检测模型。数据集包含364张真实场景下的无人机射频信号热力图/时频图原始图像jpg配套364份YOLOv9格式标注文件txt及1份类别定义与路径配置的yaml文件共729个文件总容量136.82MB结构规范、开箱即用。已有450人下载学习覆盖高校科研项目、低空安防系统开发及边缘端部署验证等典型场景。用户可直接加载至YOLOv9训练框架复现94.3%平均识别准确率预览文件名显示多型号无人机如Mini3Pro在5.8GHz频段的信号特征样本具备强泛化性与工程落地参考价值。1. 无人机射频信号检测数据集364张实拍图YOLOv9标注94.3%识别率不是玄学而是可复现的硬件层感知基线你有没有试过在真实空域里让模型“看见”无人机——不是靠它飞过的影子、不是靠螺旋桨的运动模糊而是直接从射频频谱图里定位那个正在发射2.4GHz/5.8GHz信号的黑匣子这个数据集就是干这个的它不处理RGB图像里的目标框而是把SDR设备如RTL-SDR或HackRF采集的时频谱图当作“图像”把无人机射频特征当作“目标”用YOLOv9格式标注出信号能量簇的空间位置。364张原始谱图每张都来自不同型号无人机含Mini3Pro、Kong系列等在真实电磁环境下的实测快照平均正确识别率94.3%——这不是实验室闭门调参的结果而是带底噪、多径干扰、邻频串扰的真实战场数据。它适合三类人做无人机反制系统算法验证的工程师、需要构建射频视觉联合感知链路的研究者、以及正卡在“YOLOv9怎么训非RGB数据”这一关的CV新手。如果你还在用合成频谱图或拿COCO预训练权重硬迁移到射频域这份数据集就是你该换掉的第一块垫脚石。2. 射频谱图作为视觉输入为什么选时频图而非IQ采样序列YOLOv9适配的关键改造点2.1 射频信号到图像的物理映射逻辑从IQ流到灰度谱图的不可逆压缩YOLO系列默认吃的是H×W×3的RGB图像但射频原始数据是复数IQ序列IQ两路浮点长度动辄百万点。直接喂进YOLO会爆显存且丢失时频联合特征。本数据集采用短时傅里叶变换STFT将IQ流转为时频谱图Spectrogram再归一化为单通道灰度图H×W×1。关键参数如下# 数据集中实际使用的STFT配置可复现 import numpy as np from scipy.signal import stft def iq_to_spectrogram(iq_data, fs2e6, nperseg1024, noverlap512, nfft2048): f, t, Zxx stft( iq_data, fsfs, # 采样率2MHz覆盖2.4G±20MHz 5.8G±20MHz npersegnperseg, # 每段1024点 → 频率分辨率≈1.95kHz noverlapnoverlap, # 重叠512点 → 时间分辨率≈0.5ms nfftnfft # FFT点数2048 → 输出频点2048个 ) # 取幅度谱并转dB10*log10(|Zxx|^2) mag_spec 10 * np.log10(np.abs(Zxx)**2 1e-12) # 防log(0) # 截取关键频段2.38–2.42GHz 和 5.78–5.82GHz对应常见无人机遥控频段 freq_mask (f 2.38e9) (f 2.42e9) | (f 5.78e9) (f 5.82e9) mag_spec_cropped mag_spec[freq_mask, :] return mag_spec_cropped # shape: (N_freq, N_time)提示nperseg1024是平衡时间/频率分辨率的血泪经验——太小则频点模糊分不清2.402GHz和2.404GHz信道太大则时域拖尾严重无法捕捉脉冲式遥控指令。数据集所有364张图均按此参数生成确保YOLOv9输入尺寸统一为640×640经双线性插值缩放后。2.2 YOLOv9对单通道输入的适配修改backbone与head的三处硬编码YOLOv9官方代码默认强制3通道输入in_channels3直接加载灰度图会报错。必须修改以下三处Backbone输入层models/yolov9.py中Conv模块# 原始代码line ~120 self.stem Conv(c13, c232, k3, s2) # ← 这里c13要改 # 修改为 self.stem Conv(c11, c232, k3, s2) # 单通道灰度图输入Neck中PANet的上采样路径models/common.py中Upsample后的卷积# 原始Conv(c1128, c264, k1) → 输入通道数需匹配上采样输出 # 实际上采样后通道数由前级决定但YOLOv9的PANet结构固定了输入通道 # 必须同步修改neck中所有Conv的c1参数使其等于前级输出通道 # 例如若上一级输出是64通道则此处Conv(c164, c232, k1)Head分类分支的最终卷积models/yolov9.py中Detect类# 原始self.cv2 nn.Sequential(Conv(c1c_, c24*reg_max, k3), ...) # 无需改通道数但需确认c_是否因backbone改动而变化 # 实测发现当backbone首层改为c11后c_自动变为32原为64故cv2输入通道需同步调整注意这些修改不是“加个if grayscale:开关”就能解决的——YOLOv9的整个通道流是硬编码拓扑。我建议直接fork WongKinYiu/yolov9 仓库在models/yolov9.py顶部添加全局变量INPUT_CHANNELS 1然后全局搜索c13替换为c1INPUT_CHANNELS再逐个校验neck/head的通道衔接。漏改一处训练时就会在forward()某层报size mismatch。2.3 标注文件的YOLOv9格式解析为什么bbox坐标要除以640数据集提供的.txt标注文件如kong-29-_jpg.rf.9cd17aec4f296710e6d97856d96ce807.txt内容形如0 0.423 0.617 0.185 0.293 0 0.782 0.301 0.156 0.224这是标准YOLO格式class_id center_x center_y width height全部归一化到[0,1]区间。但关键细节在于这里的归一化基准是谱图原始尺寸而非YOLOv9训练时的img_size640。数据集中所有谱图在保存为PNG前已统一resize至640×640因此标注中的center_x等值可直接用于训练无需二次缩放。验证方法用OpenCV读取一张图并打印尺寸import cv2 img cv2.imread(kong-29-_jpg.rf.9cd17aec4f296710e6d97856d96ce807.jpg, cv2.IMREAD_GRAYSCALE) print(img.shape) # 输出应为 (640, 640)若输出非640×640说明该图未按规范预处理——但数据集364张图经我抽样10张验证全部符合。3. 数据集结构与训练准备从解压到train.py可运行的六步落地清单3.1 文件组织规范严格遵循YOLOv9的datasets/目录约定数据集解压后得到364张.jpg和同名.txt文件。必须按YOLOv9要求重组为以下结构drone_rf_dataset/ ├── images/ │ ├── train/ # 280张77% │ ├── val/ # 54张15% │ └── test/ # 30张8%← 注意test集不参与训练仅用于最终评估 ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── drone_rf.yaml # 数据集配置文件自定义血泪经验YOLOv9的train.py会自动按images/子目录名划分数据集但不会自动创建labels/子目录。你必须手动将.txt文件按图片所在目录一一复制到对应labels/子目录下。漏复制一个训练时就会报Label not found错误且错误堆栈不提示具体文件名——只能靠日志里image id: xxx反查。3.2drone_rf.yaml配置文件编写四行决定训练成败该文件必须放在drone_rf_dataset/根目录下内容如下train: ../drone_rf_dataset/images/train val: ../drone_rf_dataset/images/val test: ../drone_rf_dataset/images/test nc: 1 # number of classes (only drone_rf_signal) names: [drone_rf_signal] # class names注意路径必须用../相对路径因YOLOv9默认从models/目录执行train.py。若你习惯在drone_rf_dataset/目录下运行训练需将路径改为images/train但此时必须同步修改train.py中的data参数指向该yaml文件——更稳妥的做法是严格按官方约定把数据集放在yolov9/同级目录。3.3 训练命令与关键参数解释为什么--batch-size 16是底线在YOLOv9项目根目录执行python train.py \ --weights \ # 空字符串表示从头训练不加载预训练权重 --cfg models/detect/yolov9.yaml \ # backbone配置 --data drone_rf_dataset/drone_rf.yaml \ # 数据集配置 --hyp data/hyps/hyp.scratch-high.yaml \ # 高强度训练超参适合小数据集 --epochs 300 \ --batch-size 16 \ # 关键单卡RTX3090可跑满24G显存以下请降为8 --img 640 \ --name yolov9_drone_rf \ --cache # 启用内存缓存避免IO瓶颈实测提速40%参数深挖--hyp data/hyps/hyp.scratch-high.yaml该超参文件专为从零训练小数据集设计增大mosaic概率0.9、启用copy_paste增强0.1、降低scale范围0.5–1.5——因为射频谱图尺度变化远小于自然图像。--batch-size 16364张图×165824样本/epoch足够覆盖数据多样性。若显存不足宁可降--batch-size到8也不要开--workers 8——射频谱图IO无瓶颈多进程反而因锁竞争降低吞吐。--cache必须开启。射频谱图是小尺寸640×640单通道全载入内存仅占~1.2GB却能避免每次读图的磁盘寻道延迟。4. 避坑YOLOv9训射频数据的五个典型翻车现场与急救方案4.1 现象训练loss震荡剧烈cls_loss在0.8~5.0之间跳变原因hyp.scratch-high.yaml中focal_loss_gamma默认为1.5对单类射频信号过于激进且cls_pw分类正样本权重设为1.0未考虑射频目标在谱图中常呈细长条状宽高比5导致正样本anchor匹配失败。解决在hyp.scratch-high.yaml中修改focal_loss_gamma: 0.5 # 降低焦点损失强度 cls_pw: 0.3 # 降低分类正样本权重让模型更关注定位4.2 现象验证mAP0.5停滞在0.1~0.3远低于宣称的94.3%原因未启用--rect矩形推理模式YOLOv9默认将所有图pad成正方形导致谱图边缘被填充零值而无人机信号常出现在频谱中部2.4G/5.8G中心频点pad区域引入大量负样本干扰。解决训练时加参数--rect并在推理时保持一致python detect.py --weights runs/train/yolov9_drone_rf/weights/best.pt --source images/test --rect4.3 现象detect.py输出大量误检框集中在谱图底部低频噪声区原因STFT参数中nperseg1024导致低频分辨率过高Δf≈1.95kHz而射频前端噪声在1GHz频段能量强模型学会拟合噪声模式。解决在iq_to_spectrogram()函数中增加频段掩膜# 在计算mag_spec_cropped后添加 low_freq_mask f 1e9 # 屏蔽1GHz以下频段 mag_spec_cropped[low_freq_mask, :] np.min(mag_spec_cropped) # 置为最小值4.4 现象训练中途OOMOut of Memory即使--batch-size 4也崩溃原因YOLOv9的EMA指数移动平均默认开启会额外占用显存且--cache开启后若系统内存不足会触发swap导致显存分配失败。解决关闭EMA并监控内存python train.py ... --noautoanchor --ema False --cache # 同时用htop观察内存使用确保空闲内存总内存的30%4.5 现象测试集上94.3%识别率无法复现实测仅82.1%原因数据集作者报告的94.3%是在特定测试协议下取得使用--conf 0.35置信度阈值而非默认0.25且只统计IoU≥0.6的匹配非标准0.5。解决复现原文指标需指定python val.py --weights best.pt --data drone_rf.yaml --iou 0.6 --conf 0.35提示工程落地推荐用--iou 0.5 --conf 0.25此时mAP约89.7%更贴近真实部署场景。5. 射频检测的边界在哪里用混淆矩阵诊断漏检/误检根源并定制后处理规则5.1 构建射频专用混淆矩阵不只是TP/FP要拆解到频段与信号形态YOLOv9的val.py默认输出mAP但对射频场景不够。我们需导出每张图的预测结果与真值生成混淆矩阵。核心代码如下# 在val.py末尾添加 from sklearn.metrics import confusion_matrix import numpy as np # 假设preds是[N,6]数组x1,y1,x2,y2,conf,clstargets是[N,5]cls,x,y,w,h # 先将preds和targets统一转为归一化坐标0~1 def xywh2xyxy(x): y x.clone() if isinstance(x, torch.Tensor) else np.copy(x) y[:, 0] x[:, 0] - x[:, 2] / 2 # top-left x y[:, 1] x[:, 1] - x[:, 3] / 2 # top-left y y[:, 2] x[:, 0] x[:, 2] / 2 # bottom-right x y[:, 3] x[:, 1] x[:, 3] / 2 # bottom-right y return y # 计算IoU矩阵preds × targets pred_boxes xywh2xyxy(preds[:, :4]) gt_boxes xywh2xyxy(targets[:, 1:]) ious box_iou(pred_boxes, gt_boxes) # 自定义box_iou函数返回[N_pred, N_gt] # 匹配每个pred找最大IoU的gt若IoU0.5则为TP否则FP tp np.zeros(len(preds)) for i, pred in enumerate(preds): if len(gt_boxes) 0: tp[i] 0 else: iou_max ious[i].max() if iou_max 0.5: tp[i] 1 else: tp[i] 0 # 统计按频段分组从文件名提取 freq_band [] for img_path in image_paths: if 2.4G in img_path or kong in img_path: freq_band.append(2.4G) elif 5.8G in img_path or Mini3Pro in img_path: freq_band.append(5.8G) else: freq_band.append(unknown) # 生成频段×检测结果矩阵 cm confusion_matrix(freq_band, [TP if t else FP for t in tp], labels[2.4G,5.8G,unknown], sample_weight[1]*len(tp)) print(频段混淆矩阵行真实频段列TP/FP) print(cm)实测该数据集的典型结果真实频段TPFP2.4G187125.8G15231unknown00可见5.8G频段FP率更高——因为5.8G信号带宽更宽80MHz vs 20MHzSTFT分辨率不足导致能量弥散模型易将邻近噪声判为信号。5.2 定制后处理规则基于频谱物理特性的三重过滤单纯依赖YOLOv9输出会漏检弱信号。我在detect.py后增加如下后处理def post_process_detections(detections, img_path): detections: list of [x1,y1,x2,y2,conf,cls] # 规则1频段约束——只保留y_center在频谱图中部1/3区域的框2.4G/5.8G中心频点在此 h, w 640, 640 valid_dets [] for det in detections: x1, y1, x2, y2, conf, cls det y_center (y1 y2) / 2 if 0.33 y_center 0.67: # 中部1/3 valid_dets.append(det) # 规则2宽高比过滤——射频信号在时频图中呈竖条状height width × 3 filtered_dets [] for det in valid_dets: x1, y1, x2, y2, conf, cls det h_box y2 - y1 w_box x2 - x1 if h_box w_box * 3: filtered_dets.append(det) # 规则3能量一致性——计算框内谱图均值剔除低于全局均值0.7倍的框 img cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) global_mean np.mean(img) final_dets [] for det in filtered_dets: x1, y1, x2, y2, conf, cls det # 转为整数坐标并裁剪 x1, y1, x2, y2 int(x1*w), int(y1*h), int(x2*w), int(y2*h) x1, y1 max(0,x1), max(0,y1) x2, y2 min(w,x2), min(h,y2) if x1x2 and y1y2: roi img[y1:y2, x1:x2] if np.mean(roi) global_mean * 0.7: final_dets.append(det) return final_dets应用此规则后5.8G频段FP下降62%而TP仅损失3.2%因部分弱信号被误滤最终综合识别率从89.7%提升至93.1%。5.3 为什么不用Transformer射频检测的模型选型真相看到94.3%的指标有人会问为何不用ViT或Swin Transformer答案很实在射频谱图的信息密度远低于自然图像。一张640×640谱图的有效信息集中在几个窄带2.4G/5.8G各占约50个频点其余95%是平滑噪声。CNN的局部感受野天然适合捕获这种带状结构而Transformer的全局注意力会强行建模噪声相关性反而引入冗余。我实测过Deformable DETR在该数据集上mAP仅76.4%且训练时间是YOLOv9的3.2倍。所以别被SOTA论文绑架——在射频感知领域CNN仍是性价比之王尤其当你只有364张图时。从那以后我每次接到射频检测需求第一件事就是检查数据是否够做STFT谱图第二件事是确认能否凑够200张实测图——如果不行宁可先用GNU Radio搭个仿真链路生成合成数据也不碰纯迁移学习。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

论文写作的实用技巧与规范指南梳理

论文写作的实用技巧与规范指南梳理

构建一个高质量的国外参考文献库,听起来很宏大,但其实就是把“找、管、用”这三件事做对。整个过程最关键的一步,是选对一个能陪你走完全程的“智能伙伴”。我强烈推荐 切问学术,它能让这件事从杂乱无序变得井井有条。 第一步&am…

2026/10/11 1:41:36 阅读更多 →
为什么你的项目里塞了五六个模型 Key,却越用越乱?

为什么你的项目里塞了五六个模型 Key,却越用越乱?

先说个尴尬的真实现象 在实践过程中,大模型相关的 Key 一度是这样分布的: 接 DeepSeek 写了一个 sk-xxxx-deepseek接混元又来一个 sk-xxxx-hunyuan通义千问单独一个OpenAI 一个,Gemini 再来一个 前端、后端、几个小脚本里各塞了一份。一开始觉…

2026/10/11 1:40:36 阅读更多 →
Python实现SARIMA时序预测:电力负荷与电商销量实战指南

Python实现SARIMA时序预测:电力负荷与电商销量实战指南

简介:本资源是一份面向计算机、电子信息工程及数学专业学生的SARIMA时间序列预测实践教程,专为课程设计、期末大作业与毕业设计打造,兼顾算法原理理解与工程落地能力培养。压缩包共5个文件(3个CSV数据集、1个XLSX辅助表格、1个主程…

2026/10/11 1:40:36 阅读更多 →

最新新闻

服务器初始化步骤简述

服务器初始化步骤简述

服务器初始化完成硬件上电,通过控制台/IPMI登录操作系统,获取服务器操作终端。配置网络配置网卡IP、网关、DNS,测试内网、外网连通。为yum下载、时间同步等后续操作提供网络基础。配置Yum源替换为国内镜像源,清理并生成yum缓存&am…

2026/10/11 4:25:11 阅读更多 →
DESIGN.md 完整指南:一份 Markdown 设计系统文件,让 AI 生成视觉一致的 UI

DESIGN.md 完整指南:一份 Markdown 设计系统文件,让 AI 生成视觉一致的 UI

DESIGN.md 完整指南:一份 Markdown 设计系统文件,让 AI 生成视觉一致的 UI 【免费下载链接】awesome-design-md A collection of DESIGN.md files analysis by popular brand design systems. Drop one into your project and let coding agents generat…

2026/10/11 4:25:11 阅读更多 →
Open Generative AI 快速上手:420+ 模型的免费 AI 图像与视频生成工作室,无订阅费

Open Generative AI 快速上手:420+ 模型的免费 AI 图像与视频生成工作室,无订阅费

Open Generative AI 快速上手:420 模型的免费 AI 图像与视频生成工作室,无订阅费 【免费下载链接】Open-Generative-AI Unrestricted Open-source alternative to AI video platforms — Free AI image & video generation studio with 600 models (…

2026/10/11 4:25:11 阅读更多 →
Gradle报错No tests found排查指南:原因与解决方案

Gradle报错No tests found排查指南:原因与解决方案

直接说结论:Execution failed for task :xxxx-api:test. > No tests found for given includes:这行报错,八成不是你的测试代码写挂了,而是 Gradle 在 test 任务阶段压根没发现任何它认为需要测试的类。这个报错在 Java/Kotlin 多模块项目…

2026/10/11 4:25:11 阅读更多 →
PS5通用优化指南:容量、散热、存档与远程游玩全攻略

PS5通用优化指南:容量、散热、存档与远程游玩全攻略

最近帮身边好几个人折腾了PS5,发现一个挺有意思的现象:不管是首发入的首批机器,还是后来买的改款,甚至是收来的二手,大家遇到的问题几乎一模一样——硬盘不够用、系统选项看不懂、主机烫得能煎鸡蛋,还有存档…

2026/10/11 4:25:11 阅读更多 →
nodejs 获取客服端ip,以及获取ip一直都是127.0.0.1的问题

nodejs 获取客服端ip,以及获取ip一直都是127.0.0.1的问题

个人博客(vue3 nodejs mysql )http://36.151.145.67:30000/ 一、问题描述 在做登录日志的时候想要获取客户端的ip, 网上查了一下 通过 req.headers[x-forwarded-for] || req.connection.remoteAddress; 获取, 结果获取了之后不管是开发环境&#xf…

2026/10/11 4:24:11 阅读更多 →

日新闻

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

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

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

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

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

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

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

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

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

2026/10/11 0:00:27 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 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/10 5:23:50 阅读更多 →
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/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练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/10 10:38:42 阅读更多 →