手机使用检测工程包:YOLO数据集与PyQt5界面实战
简介本资源面向计算机视觉学习者与行为分析研究者提供一套基于YOLOv13的手机使用检测完整方案可用于课堂专注度观察、办公场景手机使用习惯研究等目标检测实践。压缩包共约2000个文件以1980个txt标注文件为主另含18个md说明文档、1个yaml数据配置与1份pdf资料整体约345MB目录结构清晰便于按模块查阅。数据集已划分train、val、test并附data.yaml可直接用于yolov5至v12等系列算法训练类别为phone手机。资源同时包含训练好的模型与PyQt5可视化界面并配有使用教程读者可快速完成检测演示与结果查看。目前已有35人学习适合希望从数据标注、模型训练到界面部署完整走通一遍的中级开发者参考。1. 手机使用检测这套资源到底能帮你省掉哪些重复劳动实验室里做行为分析最耗时的往往不是模型调参而是从零攒一份能直接开训的数据集。这套资源把「手机使用检测」这个具体场景的标注数据、训练好的权重和 PyQt5 可视化界面打包在一起拿到手就能跑推理、看效果、改界面。它解决的是「有想法但缺数据缺界面」的卡点适合做课堂行为分析、驾驶分心监测、办公场景手机使用习惯研究的人。数据集标注了 phone 这一类YOLO 格式的 txt 和 VOC 格式的 xml 都给了train/val/test 已经切分好data.yaml 也配好了yolov5 到 yolov12 系列都能直接接。PyQt5 界面负责把检测结果可视化出来不用自己从 QLabel 开始搭。一句话这是一份能让你跳过数据清洗和界面搭建、直接进入模型验证和业务逻辑调试的工程包。2. 数据集结构与 YOLO 格式转换从 xml 到 txt 的完整链路2.1 为什么同时给 YOLO 和 VOC 两套标签YOLO 系列训练读的是归一化后的 txt每行class_id x_center y_center width height坐标都是相对图像宽高的比例值。VOC 的 xml 则是绝对像素坐标xmin ymin xmax ymax四个角点。两套都留着是因为不同工具链吃的东西不一样labelImg 默认存 xml而 ultralytics 的 DataLoader 只认 txt。资源里两套并存意味着你可以用 xml 做标注复核和可视化画框用 txt 直接喂训练不用来回转。常见做法是拿 xml 当「原始档案」txt 当「训练副本」改标注时先动 xml 再重新导出 txt避免直接改 txt 导致坐标对不上。2.2 目录组织与 data.yaml 的字段含义拿到包之后先别急着训把目录结构看清楚。典型布局是这样dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamlimages 和 labels 下的子目录名必须一一对应train 的图配 train 的标签错一个就全乱。data.yaml 里通常长这样path: ./dataset train: images/train val: images/val test: images/test nc: 1 names: [phone]path是数据集根目录train/val/test是相对 path 的路径nc是类别数names是类别名列表。这里 nc1、names 只有 phone说明是单类检测。如果你后面要加「人脸」或「手持姿态」这类新类改 nc 和 names 的同时txt 里的 class_id 也要跟着改否则模型会把新类当成 phone 学。2.3 用脚本把 VOC 的 xml 批量转成 YOLO 的 txt资源里虽然两套都有但如果你自己补标了一批 xml就得转。下面这个脚本我常用读 images 目录找同名 xml输出到 labels 目录import os import xml.etree.ElementTree as ET from PIL import Image # 类别映射顺序必须和 data.yaml 的 names 一致 CLASS_MAP {phone: 0} def convert(xml_dir, img_dir, out_dir): os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() # 用对应图像的真实宽高做归一化不能拿 xml 里的 size 凑合 img_name xml_file.replace(.xml, .jpg) img_path os.path.join(img_dir, img_name) if not os.path.exists(img_path): print(f缺图跳过: {img_name}) continue w, h Image.open(img_path).size lines [] for obj in root.findall(object): name obj.find(name).text if name not in CLASS_MAP: continue bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 转成中心点加宽高的归一化格式 xc (xmin xmax) / 2.0 / w yc (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{CLASS_MAP[name]} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) with open(os.path.join(out_dir, xml_file.replace(.xml, .txt)), w) as f: f.write(\n.join(lines)) convert(dataset/xml, dataset/images/train, dataset/labels/train)逻辑上就三步解析 xml 拿绝对坐标用图像真实宽高归一化按类别映射写 txt。参数上注意CLASS_MAP的 value 必须和 data.yaml 的 names 索引对齐Image.open读的是原图尺寸而不是 xml 里声明的 size因为有些标注工具会写错 size 字段。跑完抽查几个 txt用cat看一眼数值是不是都在 0 到 1 之间出现大于 1 的基本就是宽高取反了。2.4 划分 train/val/test 的注意点资源已经切好了但如果你自己扩数据别用随机切分。手机使用检测的图像往往来自连续视频帧相邻帧几乎一样随机切会让同一场景的帧同时进 train 和 val验证指标虚高。常见做法是按视频源或时间段切前 70% 时间段的帧进 train中间 15% 进 val最后 15% 进 test。这样 val 的指标才接近真实泛化能力。切完检查一下三个子集的类别分布phone 框的数量比例别差太多差太多就在 yaml 里加augment或者对少数子集过采样。3. 用 YOLOv13 训练手机检测模型参数怎么设、日志怎么看3.1 环境准备与 ultralytics 的版本选择这套资源标称支持 yolov5 到 yolov12实际训练时我一般用 ultralytics 这个统一接口它把 v5/v8/v11 的 API 拉齐了换模型只改一行。装的时候注意 Python 版本别太低3.9 以上比较稳pip install ultralytics8.3.0 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121第二行是按 CUDA 12.1 装的 torch如果你机器是 CUDA 11.8把 cu121 换成 cu118。装完跑yolo checks看环境重点看 CUDA 是否可用、显存多大。显存 8G 以下建议把 batch 降到 8 或 4不然第一个 epoch 就 OOM。3.2 训练命令与关键参数逐项说明假设 data.yaml 在 dataset 目录下模型权重用资源里给的预训练权重yolo detect train \ datadataset/data.yaml \ modelyolov13n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/phone \ nameexp1data指向 yamlmodel是初始权重epochs是总轮数imgsz是输入分辨率batch是批大小lr0是初始学习率patience是早停耐心值连续 20 轮 val 指标不升就停。project和name决定日志和权重的落盘位置。手机检测这种单类任务100 轮通常够如果 val 的 mAP 在 60 轮后还在涨可以加到 150。lr0 默认 0.01 对单类偏大如果 loss 震荡厉害降到 0.005 再试。3.3 训练日志里该盯哪几个数跑起来之后终端会刷一堆指标别只看 mAP50。重点看三个box_loss是否稳定下降cls_loss是否收敛到接近 0mAP50-95是否在涨。如果 box_loss 降但 mAP 不涨多半是标注框质量有问题回去抽查 txt 和原图的对齐情况。如果 cls_loss 一直不降检查 data.yaml 的 nc 和 names 是否和 txt 里的 class_id 对得上。资源里只有 phone 一类cls_loss 理论上应该很快压下去压不下去就是标签有脏数据。3.4 用训练好的权重做推理验证训完或者直接用资源里给的权重跑单张图看效果yolo detect predict \ modelruns/phone/exp1/weights/best.pt \ sourcetest_images/ \ conf0.25 \ saveTrueconf是置信度阈值0.25 是常用起点。手机检测场景里如果画面里手机小且多conf 可以降到 0.15 召回更多但误检也会涨。跑完看runs/detect/predict下的图重点看漏检和误检分别出现在什么场景逆光、遮挡、手持角度偏的时候漏检多说明训练集缺这类样本得补数据而不是调阈值。4. PyQt5 可视化界面把检测结果接进桌面应用4.1 界面整体结构与信号槽机制PyQt5 做检测界面核心就三块左边 QLabel 显示图像右边 QPushButton 触发检测底部 QTextEdit 打日志。信号槽是 Qt 的命脉按钮的clicked信号连到你的检测函数检测函数跑完再发一个自定义信号把结果传回主线程更新 QLabel。别在按钮回调里直接跑推理推理耗时几百毫秒到几秒会把界面卡死用户以为程序崩了。常见做法是开一个 QThread 跑推理通过pyqtSignal把带框的图像和统计信息发回主线程。4.2 加载模型与图像显示的代码骨架下面这段是界面里最核心的推理加显示逻辑import sys import cv2 from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QVBoxLayout, QWidget from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtCore import QThread, pyqtSignal from ultralytics import YOLO class InferThread(QThread): # 自定义信号传回带框图像和检测数量 result_ready pyqtSignal(object, int) def __init__(self, model, img_path): super().__init__() self.model model self.img_path img_path def run(self): results self.model(self.img_path, conf0.25) # plot 返回带框的 numpy 数组BGR 格式 annotated results[0].plot() self.result_ready.emit(annotated, len(results[0].boxes)) class MainWindow(QMainWindow): def __init__(self): super().__init__() self.model YOLO(best.pt) self.label QLabel(等待检测) self.btn QPushButton(选择图片并检测) self.btn.clicked.connect(self.on_click) layout QVBoxLayout() layout.addWidget(self.label) layout.addWidget(self.btn) container QWidget() container.setLayout(layout) self.setCentralWidget(container) def on_click(self): # 实际项目里用 QFileDialog 选文件这里写死路径演示 self.thread InferThread(self.model, test.jpg) self.thread.result_ready.connect(self.show_result) self.thread.start() def show_result(self, img, count): # OpenCV 是 BGRQt 要 RGB转换顺序别搞反 rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) h, w, ch rgb.shape qimg QImage(rgb.data, w, h, ch * w, QImage.Format_RGB888) self.label.setPixmap(QPixmap.fromImage(qimg)) self.setWindowTitle(f检测到 {count} 个手机) app QApplication(sys.argv) win MainWindow() win.show() sys.exit(app.exec_())逻辑上InferThread继承 QThreadrun里调模型plot()直接返回画好框的图省得自己写画框代码。result_ready信号带两个参数一个是图像数组一个是检测框数量。主线程的show_result负责把 BGR 转 RGB 再塞进 QLabel。参数上注意QImage的构造需要传 bytesPerLine也就是ch * w传错会花屏。conf和训练时保持一致不然界面里看到的框和验证时对不上。4.3 把检测数量和行为统计接进界面光显示框还不够行为分析要的是统计。在show_result里可以顺手算当前帧检测到几个 phone连续多少帧都有 phone用来判断「持续使用」还是「短暂拿起」。常见做法是维护一个滑动窗口比如最近 30 帧里有 20 帧检测到 phone就标记为「正在使用」。这个逻辑放在主线程里做因为推理线程只管出框业务判断放主线程方便改阈值。界面底部加个 QTextEdit每次检测完追加一行「时间戳 数量 状态」导出成 CSV 就是使用习惯的原始记录。5. 避坑与排查标注、训练、界面三段的血泪经验5.1 现象训练 loss 正常但 mAP 一直是 0原因data.yaml 里的names和 txt 里的 class_id 对不上或者 txt 路径和 images 路径没对齐。YOLO 读标签是按 images 路径替换成 labels 去找的目录名差一个字母就全读不到读不到标签时 loss 会算成背景mAP 自然为 0。解决先跑一遍yolo detect train加--verbose看它打印的train: Scanning...后面跟的图片数和标签数是否一致。不一致就检查 images 和 labels 的子目录名是否严格对应再抽查一个 txt 的 class_id 是否在 names 范围内。5.2 现象PyQt5 界面点按钮后直接卡死原因推理函数写在主线程的按钮回调里模型加载和推理都是阻塞操作主线程被占住Qt 的事件循环转不动界面就不刷新了。解决把推理放进 QThread 或 QRunnable通过信号把结果发回主线程。注意 QThread 的对象要在主线程创建run里别碰界面控件只发信号。如果推理要连续跑视频流用 QTimer 定时触发或者用线程池别在run里写死循环。5.3 现象界面显示的框位置偏移或颜色错乱原因OpenCV 读图是 BGRQt 的 QImage 默认按 RGB 解析不转换的话红蓝通道互换框的颜色和原图都对不上。另外QImage构造时 bytesPerLine 传成w * 3在某些宽度下会错位因为 Qt 要求按 4 字节对齐。解决统一在显示前做cv2.cvtColor(img, cv2.COLOR_BGR2RGB)bytesPerLine 用rgb.strides[0]而不是自己算。如果还偏检查plot()返回的图是否被 resize 过QLabel 的setScaledContents(True)会拉伸图像但不会改坐标框会跟着拉伸看起来偏但实际是显示缩放导致的。5.4 现象验证集 mAP 很高实际用的时候漏检严重原因train/val/test 是按随机切分做的同一段视频的相邻帧被分到了不同子集验证集里全是训练集见过的场景指标虚高。解决按视频源或时间段重新切分确保 val 和 test 里的场景在 train 里没出现过。切完再训一遍mAP 会掉几个点但那个数才是真实水平。如果掉太多说明模型泛化不够加数据增强或者换更大的模型。5.5 现象推理时显存够但速度很慢原因imgsz设得太大或者没开半精度。手机检测这种单类任务640 通常够设到 1280 速度直接砍半。另外 PyTorch 默认 FP32开 FP16 能快 30% 左右。解决推理时加halfTrueimgsz从 640 起步不够再往上加。如果用的是 CPU 推理把devicecpu显式写上别让它自动选有时候自动选会走到集显上反而更慢。6. 进阶把检测结果变成使用习惯的时间序列界面跑通之后真正有价值的是把逐帧检测变成行为指标。我一般会在 PyQt5 里加一个后台线程按固定间隔比如每秒 2 次抓帧推理把「时间戳、检测数量、置信度均值」写进 SQLite。攒够一天的数据用 pandas 做滑动平均就能看出「上午 10 点手机使用最频繁」这类规律。下面这段是统计逻辑的骨架import sqlite3 import pandas as pd conn sqlite3.connect(usage.db) # 按分钟聚合算每分钟平均检测数量和最大置信度 df pd.read_sql(SELECT ts, count, conf FROM detections, conn) df[ts] pd.to_datetime(df[ts]) df.set_index(ts, inplaceTrue) per_min df.resample(1min).agg({count: mean, conf: max}) # 标记持续使用连续 5 分钟平均数量大于 0.5 per_min[using] (per_min[count] 0.5).rolling(5).sum() 5 print(per_min[per_min[using]].head(20))resample(1min)把逐帧记录压成分钟级rolling(5).sum() 5判断最近 5 分钟是否持续有手机。阈值 0.5 和 5 这两个数按场景调课堂场景可以放宽到 0.3驾驶场景要收紧到 0.8。导出的 CSV 可以直接喂给可视化库画热力图按小时和星期几交叉看使用习惯的峰谷就出来了。验证模型有没有过拟合我习惯留一段完全没参与训练的视频跑完统计漏检率和误检率。漏检率高于 15% 就补对应场景的数据误检率高于 10% 就检查是不是把手机壳、遥控器这类相似物体标成了 phone。这套流程走下来从数据到界面到行为分析就闭环了。从那以后我每次拿到新的检测包都先跑一遍单张推理确认标签对齐再开界面最后才上统计顺序反了就得返工。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Windows 上 WSL2 内核级 Linux 加 GPU 直通:AI 开发环境部署与调优实战

Windows 上 WSL2 内核级 Linux 加 GPU 直通:AI 开发环境部署与调优实战

1. 为什么要在 Windows 上折腾内核级 Linux 加 GPU 直通如果你是一个长期在 Windows 上做 AI 开发的从业者,大概率经历过这样的纠结:Windows 的桌面生态和办公软件确实方便,但一到跑模型训练、装 CUDA 工具链、配各种 Python 依赖的时候&…

2026/10/13 22:34:37 阅读更多 →
open-code-review:构建开放协作的代码审查机制

open-code-review:构建开放协作的代码审查机制

1. 从“open-code-review”这个标题说起:它到底想解决什么问题第一次看到“open-code-review”这个标题,我脑子里蹦出来的第一个念头是:这大概率不是一个单纯的代码审查工具,而是一套把“审查”这件事从封闭走向开放的机制设计。为…

2026/10/12 21:37:36 阅读更多 →
aiogram 中 BotCommandScopeChatMember 详解:为群组特定成员定制 Bot 命令作用域

aiogram 中 BotCommandScopeChatMember 详解:为群组特定成员定制 Bot 命令作用域

后端即时通讯API设计 【免费下载链接】aiogram aiogram is a modern and fully asynchronous framework for Telegram Bot API written in Python using asyncio 项目地址: https://gitcode.com/gh_mirrors/ai/aiogram 点击查看 免费下载 导读 BotCommandScopeCha…

2026/10/14 0:04:43 阅读更多 →

最新新闻

Django+小程序搭建工厂定制化ERP系统:设计与实现

Django+小程序搭建工厂定制化ERP系统:设计与实现

1. 先弄清楚这个项目到底解决什么问题1.1 工厂为什么需要"定制化"ERP最近后台私信里问得最多的,就是毕业设计选题怎么选。很多同学一上来就问"有没有好过的题目",但我更建议大家先想清楚一个问题:这个题目做出来&#xf…

2026/10/14 3:54:41 阅读更多 →
微信二次开发如何设计消息回看标记?WechatApi 多人工作台中避免“有人看过”被误认为“已经处理”

微信二次开发如何设计消息回看标记?WechatApi 多人工作台中避免“有人看过”被误认为“已经处理”

官网友情链接 wechatapi.net 个人微信二次开发做多人工作台时,消息往往会展示: 未读; 已读。 这对于普通聊天软件足够,但对企业客服来说远远不够。 因为一个客服打开客户会话,只能说明: 有人看过。 并不…

2026/10/14 3:54:41 阅读更多 →
OpenSSH 8.8p1源码编译升级:从tar.gz到sshd的避坑全指南

OpenSSH 8.8p1源码编译升级:从tar.gz到sshd的避坑全指南

简介:OpenSSH 8.8p1 源代码压缩包面向系统管理员、运维工程师及安全研究人员,用于在 Linux/Unix 环境中构建或升级安全的远程登录与文件传输服务。该版本为 8.8 系列的安全修补版,包含对已知漏洞的修复及兼容性改进,可满足生产环境…

2026/10/14 3:54:41 阅读更多 →
个人微信二次开发如何设计客户关系归档?WechatApi 删除好友后如何保留历史又停止当前自动化

个人微信二次开发如何设计客户关系归档?WechatApi 删除好友后如何保留历史又停止当前自动化

官网友情链接 wechatapi.net 个人微信客户删除好友以后,很多系统会陷入两个极端。 第一种: 直接删除本地客户数据。 历史聊天、CRM、工单关系全部断裂。 第二种: 什么都不做。 系统仍然把这个关系当成正常客户,继续创建自动跟…

2026/10/14 3:54:41 阅读更多 →
三剑客企业场景

三剑客企业场景

企业需求一:统计访问最多的IP 企业场景 公司网站访问速度变慢。领导要求: > "找出今天访问网站次数最多的IP,看是不是有人恶意访问。" 日志文件: access.log 运维要做的企业要求 统计: 访问次数 IP 按照次…

2026/10/14 3:54:41 阅读更多 →
虚拟电厂多时间尺度调度与储能衰减成本建模的优化框架

虚拟电厂多时间尺度调度与储能衰减成本建模的优化框架

做电力系统调度和新能源并网研究的同行,今年应该都能感觉到,讨论的话题不知不觉从“怎么把风、光消纳掉”转向了“消纳掉之后系统还稳不稳”。高比例可再生能源并网之后,麻烦的不是装机本身,而是系统里能够快速出力的灵活调节资源…

2026/10/14 3:53:40 阅读更多 →

日新闻

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 阅读更多 →