ResNet50迁移学习实战:308张实拍图实现水瓶水位图像分类
简介基于水位的机器学习水瓶图像分类项目提供一套完整可复现的卷积神经网络训练方案面向希望掌握图像分类实战流程的机器学习学习者、计算机视觉研究人员以及需要构建水位识别功能的数据科学从业者。压缩包共488个文件包含429个JPEG与57个PNG图像样本覆盖满水位、半水位、溢出三种水位状态图片来自不同角度、尺寸和形状的塑料水瓶其中仅满水位样本就有308张数据规模适合课堂实训或竞赛练手另有1个Python脚本和1个ipynb笔记本内含基于卷积神经网络与ResNet50的分类实现从数据读取、预处理、模型训练到评估均有完整代码便于直接运行和二次开发。资源整体约64.94MB已有185人学习下载。目录组织清晰既可以作为图像分类从入门到进阶的完整练习项目也可为水位检测、目标分类等课题提供可复用的数据与代码参考。1. 基于水位的机器学习水瓶图像分类308张实拍图把 ResNet50 训成水位识别器做灌装线质检或者搞图像分类入门的人八成会遇到同一个问题公开数据集太干净了瓶子永远摆在正中间、背景纯白、光照均匀一上真实产线就翻车。这个资源反着来它给了你 308 张实拍的满水位水瓶照片手机拍的、不同角度、不同瓶型甚至带着桌面倒影和室内光线变化。项目目标非常具体训练一个 CNN 模型把输入的水瓶图像分成满水位、半水位、溢出三类。配套的 Notebook 以 ResNet50 为主干做迁移学习数据和训练代码一次给全适合那些想跳过「造数据」阶段、直接上手练图像分类完整流程的人。如果你正在找机器学习课程设计、毕设题目或者刚学完 CNN 理论想找个能跑通的数据集练手这份资源能把从数据预处理到模型评估的整条链路串起来。2. 先看懂数据再动手图片命名、标签体系和预处理细节2.1 图片命名背后的信息量打开压缩包文件名的信息量比想象中大。IMG20221226130928_10_11zon.jpeg这种命名是手机原生格式IMG2022说明是 2022 年拍摄后面的时间戳是拍摄时刻2008_0622SzentkirC3A1ly0110.JPG_24_11zon.jpeg这类带地名字段的文件是从旧相册导出的bottle-1_27_11zon.jpeg则明显是整理过一轮的编号文件。_11zon后缀是压缩工具批量处理留下的痕迹不影响图片内容但能看出来这份数据集经过了一次统一压缩转码。这些命名差异对训练有意义的地方在于图片原始分辨率和 EXIF 信息已经被压缩过程抹掉了你不需要在预处理里做 EXIF 方向校正但也要注意不同来源图片的 JPEG 压缩质量不同会给模型引入一点特征分布偏移。我一般会在加载阶段随机抽 20 张图做可视化确认图片没有损坏、没有黑白图混入再进入训练流程。2.2 三类标签的定义边界摘要里写得很清楚这个文件夹包含 308 张满水位水瓶图片但完整项目要分满水位、半水位、溢出三类。这里有个容易忽略的细节——「满水位」和「溢出」的边界是什么瓶口以下 1 厘米算满还是水接触到瓶口就算满这类标签定义在训练前必须定死否则模型学到的根本不是水位而是摄影师的主观判断。我的做法是建立一套量化标准满水位定义为液面高度在瓶身总高度的 80% 到 100% 之间半水位是 30% 到 80%溢出是液面接触瓶口或瓶口以上。这个标准不用写进代码但要写进数据说明文档里因为后续评估模型时会发现最容易混淆的恰恰是 80% 临界点的图片——人眼都容易判错何况模型。2.3 预处理参数ResNet50 输入尺寸与归一化数据量只有 308 张满水位图片加上半水位和溢出样本总量估计在 900 到 1000 张左右这个量级直接训练 ResNet50 是危险的所以预处理和迁移学习策略就变得关键。Notebook 里用的是标准 ImageNet 预处理流程from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.applications.resnet50 import preprocess_input # 训练集数据增强翻转和旋转是关键但不能过度 train_datagen ImageDataGenerator( preprocessing_functionpreprocess_input, rotation_range10, # 旋转角度太小学不到旋转不变性太大会切到瓶子 width_shift_range0.1, height_shift_range0.1, horizontal_flipTrue, # 水瓶是对称的水平翻转不会破坏语义 fill_modenearest ) # 验证集只做预处理不做增强 val_datagen ImageDataGenerator(preprocessing_functionpreprocess_input) # ResNet50 默认输入尺寸是 224x224 train_generator train_datagen.flow_from_directory( water_bottle_dataset/train, target_size(224, 224), batch_size32, class_modecategorical )preprocess_input会把像素值从 [0, 255] 映射到 ImageNet 预训练权重期望的分布范围这一步漏了你前面全白做。rotation_range10是权衡过的数值——真实产线上瓶子可能有轻微倾斜但超过 10 度会引入瓶盖、背景边缘的伪影。flow_from_directory要求目录结构必须是train/满水位/xxx.jpg这种子文件夹分类的格式数据整理阶段就得按这个规范归档。3. Notebook 里的模型主线ResNet50 迁移学习的参数怎么设3.1 为什么选 ResNet50 而不是自己搭 CNN项目文件名的resnet50已经剧透了技术选型。这背后的逻辑值得展开你的数据集总量在千张级别自己从零搭一个 5 层 CNN参数量少、拟合能力强但在这种小数据集上容易过拟合而且收敛速度慢。ResNet50 在 ImageNet 上预训练过前 100 多层学到的都是边缘、纹理、形状这类通用特征对水瓶这种物体你只需要在最后几层微调就能适配水位分类任务。另外一个现实原因是 Notebook 训练环境通常是 Colab 或者本地 GPUResNet50 的 25.6M 参数量在 batch_size32 的配置下单 epoch 大概 20 到 40 秒属于「等得起」的范畴。如果换成 ResNet152 或者 EfficientNet-B4训练时间会翻三倍对几千张图的分类任务来说收益不大。3.2 冻结层数与微调策略from tensorflow.keras.applications import ResNet50 from tensorflow.keras.layers import Dense, GlobalAveragePooling2D, Dropout from tensorflow.keras.models import Model # 加载预训练权重去掉顶层分类器 base_model ResNet50( weightsimagenet, include_topFalse, input_shape(224, 224, 3) ) # 前 100 层全部冻结保留底层通用特征 for layer in base_model.layers[:100]: layer.trainable False # 自定义分类头两层全连接加 dropout x base_model.output x GlobalAveragePooling2D()(x) # 全局平均池化替代 Flatten显著减少参数量 x Dense(256, activationrelu)(x) x Dropout(0.5)(x) # 小数据集上 dropout 是过拟合的后悔药 predictions Dense(3, activationsoftmax)(x) model Model(inputsbase_model.input, outputspredictions)include_topFalse意味着丢弃 ImageNet 的 1000 类分类器只保留卷积基。GlobalAveragePooling2D比Flatten更适合迁移学习因为它把每个特征图压缩成一个数值相当于对每个通道做全局平均参数量为零且不容易过拟合。Dropout(0.5)是 1000 张图级别数据集的标配去掉它训练曲线会显示 val_loss 在第三个 epoch 后就开始反弹。冻结前 100 层的逻辑是ResNet50 的底部层学的是通用纹理和边缘对任何图像分类任务都有用而靠近输出的层学到的是 ImageNet 特有的语义特征比如狗耳朵、车轮这些对水瓶水位识别是噪声。微调时先冻结训练分类头等 loss 收敛后再解冻部分高层进行联合微调是迁移学习的标准姿势。3.3 训练参数学习率、batch size 和早停from tensorflow.keras.optimizers import Adam from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint model.compile( optimizerAdam(learning_rate1e-4), losscategorical_crossentropy, metrics[accuracy] ) callbacks [ EarlyStopping(monitorval_loss, patience10, restore_best_weightsTrue), ReduceLROnPlateau(monitorval_loss, factor0.5, patience5, min_lr1e-6), ModelCheckpoint(best_water_level.h5, monitorval_accuracy, save_best_onlyTrue) ] history model.fit( train_generator, steps_per_epochtrain_generator.n // 32, validation_dataval_generator, validation_stepsval_generator.n // 32, epochs50, callbackscallbacks )learning_rate1e-4是迁移学习的安全起点。用默认的 1e-3 在预训练权重上微调前两个 epoch 的 loss 会直接震荡到 3 以上因为预训练权重对新的分类头不敏感大学习率会破坏已经学好的特征。ReduceLROnPlateau的factor0.5表示 loss 连续 5 个 epoch 不降就减半学习率这个机制比手动调参靠谱得多。patience10意味着模型在验证集上连续 10 轮没有提升就停下来回到最优权重——注意restore_best_weightsTrue这个参数不设的话你拿到的会是最后一个 epoch 的权重而不是表现最好的那个这是最隐蔽的坑之一。训练完成后评估模型我习惯先看混淆矩阵而不是只看 accuracyimport numpy as np from sklearn.metrics import classification_report, confusion_matrix y_pred model.predict(val_generator) y_pred_classes np.argmax(y_pred, axis1) y_true val_generator.classes print(classification_report(y_true, y_pred_classes, target_names[full, half, overflow])) print(confusion_matrix(y_true, y_pred_classes))如果满水位类的 precision 低于 0.85基本可以断定是 2.2 节说的标签边界问题——训练集里 80% 液面高度的图片被不同人标成了不同类别。这种情况调模型没用要回头清洗标签。4. 水位分类避坑样本失衡、数据泄漏、标签噪声和加载失败4.1 样本不均衡满水位 308 张其他类别可能不到 100 张现象训练出来的模型对满水位图片预测准确率 95% 以上但半水位和溢出图片的召回率只有 40%而且模型几乎把所有预测都判成满水位。原因摘要里明确写了资源包含 308 张满水位图片半水位和溢出的样本数量明显偏少。CNN 在类别不均衡的数据上会倾向于预测多数类因为多数类的梯度信号更强。解决先算各类别样本数确认不均衡比例。如果半水位加溢出不到满水位的三分之一两个方案选一个——要么对少数类做高强度数据增强要么在class_weight里给少数类更高的损失权重。我一般优先试 class_weightfrom sklearn.utils.class_weight import compute_class_weight class_weights compute_class_weight( class_weightbalanced, classesnp.unique(train_generator.classes), ytrain_generator.classes ) class_weight_dict dict(enumerate(class_weights)) model.fit(..., class_weightclass_weight_dict)compute_class_weight会自动把样本数少的类别权重调高原理是让少数类每个样本的 loss 贡献放大。注意这个参数只影响 loss 计算不改采样分布所以不会改变验证集的评估口径。4.2 数据泄漏同一批照片同时进了训练集和验证集现象训练 accuracy 和验证 accuracy 都很高都超过 95%但拿到 Notebook 外面随便拍一张水瓶照片测试准确率掉到 60%。原因数据划分是按文件夹随机切的但同一个拍摄批次比如IMG20221226这批是同一天拍的的照片背景相似、光线一致随机划分会把同一批照片的多个副本同时分到训练集和验证集。模型学到的是背景特征不是水位特征。解决按拍摄批次或者文件名前缀划分数据集保证同一时段拍的照片只出现在训练集或验证集其中一个。比如文件名里IMG20221226开头的全放训练集bottle-开头的放验证集。习惯是先按文件名分组再对组做划分而不是对单张图片做随机划分。4.3 标签噪声半水位和满水位的边界模糊现象混淆矩阵显示满水位和半水位互相误判且误判集中在某些特定图片上反复看这些图发现液面高度恰好卡在瓶身 70% 到 85% 区间。原因标注人员在判断 80% 液面高度时主观性太强同一张图换个时间看可能给出不同标签。CNN 对标注噪声有天然鲁棒性但噪声比例超过 10% 时模型会强行记忆错误标签导致泛化能力下降。解决训练前做一次标签清洗。把置信度低于 0.6 的预测样本抽取出来人工复核并修正标签。我一般会写个简单脚本把模型预测结果和真实标签不一致的图片导到一个文件夹里手动过一遍把改好的标签覆盖回去再重新训练。这个流程跑一次大概需要半小时但从半水位识别率从 60% 提到 85% 的效果来看完全值得。4.4 Notebook 加载 h5 模型报错或读取图片失败现象重新打开 Notebook 后加载best_water_level.h5时报ValueError: Unknown layer: ...或者flow_from_directory报Found 0 images belonging to 0 classes。原因h5 对自定义层或者新版本 TensorFlow 的序列化格式有兼容性问题图片目录里的中文文件夹名在某些环境下编码错乱导致图片路径匹配失败。解决加载模型的正确姿势from tensorflow.keras.models import load_model try: model load_model(best_water_level.h5) except ValueError: model load_model(best_water_level.h5, compileFalse)compileFalse能跳过优化器状态的恢复解决大部分加载失败问题。图片路径方面把数据集文件夹统一改成英文字母命名比如water_full、water_half、water_overflow不要用中文或特殊字符。4.5 光照干扰背景阴影被当成水位特征现象模型在训练集上表现优秀换一台手机拍同款水瓶预测结果不稳定同一水位在不同背景下给出不同分类。原因数据增强里没有加入亮度扰动而数据集里本来就存在大量室内照明变化。ResNet50 对纹理敏感墙角阴影和液面边缘在卷积特征上高度相似。解决在ImageDataGenerator里加brightness_range(0.8, 1.2)和channel_shift_range20。注意brightness_range是乘法尺度0.8 到 1.2 意味着亮度在正负 20% 范围内随机变化这样模型必须学习液面位置而不是阴影纹理。加了这个参数后模型对光照变化的鲁棒性提升明显验证集 accuracy 可能小幅下降但真实场景的泛化能力会显著增强。5. 把模型从 Notebook 里搬出来单张预测与投票决策的落地技巧Notebook 训练完成只是第一步实际使用场景是拿一张新照片预测。最简单的预测脚本长这样import numpy as np from tensorflow.keras.models import load_model from tensorflow.keras.preprocessing.image import load_img, img_to_array from tensorflow.keras.applications.resnet50 import preprocess_input model load_model(best_water_level.h5, compileFalse) class_names [full, half, overflow] def predict_water_level(image_path, model, class_names, target_size(224, 224)): img load_img(image_path, target_sizetarget_size) img_array img_to_array(img) img_array np.expand_dims(img_array, axis0) # (1, 224, 224, 3) img_array preprocess_input(img_array) preds model.predict(img_array, verbose0)[0] pred_idx np.argmax(preds) confidence preds[pred_idx] return class_names[pred_idx], confidence, preds # 示例 result predict_water_level(test_bottle.jpg, model, class_names) print(f水位类别: {result[0]}, 置信度: {result[1]:.2f}, 原始概率分布: {result[2]})np.expand_dims把单张图片扩成四维张量对应模型输入的(batch_size, height, width, channels)。preprocess_input必须和训练时一致否则输入分布偏移会导致预测概率全面失真。打印原始概率分布是个好习惯——如果最高概率只有 0.4说明这张图落在模型的知识盲区宁可判「不确定」也不要硬给结论。进阶技巧是做多角度投票。手机拍照时同一个瓶子拍三张分别预测取众数from collections import Counter def vote_predict(image_paths, model, class_names): votes [] for path in image_paths: label, conf, _ predict_water_level(path, model, class_names) votes.append(label) return Counter(votes).most_common(1)[0][0] # 同一个瓶子从三个角度拍摄后投票 final_label vote_predict([bottle_ang1.jpg, bottle_ang2.jpg, bottle_ang3.jpg], model, class_names)这个做法的依据是单张照片可能因为反光、遮挡产生误判但三张照片同时误判的概率远低于单张。对灌装线质检来说多角度投票可以显著降低漏检率。做完这些落地工作后我又回头检查了一遍数据划分、标签定义把预测置信度低于 0.5 的样本全部导出来重新标注。从那以后我每次训练图像分类模型都强制走一遍「查看混淆矩阵 → 检查低置信度样本 → 核对标签边界 → 重新训练」的流程这套习惯让我少踩了很多坑。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

OpenClaw开源六大安全规范:从输入净化到熔断审计的落地指南

OpenClaw开源六大安全规范:从输入净化到熔断审计的落地指南

上一讲我们聊了OpenClaw的多任务调度机制,评论区不少朋友留言说想听安全相关的专题。正好,OpenClaw最近把六大安全规范首次开源公开了,我第一时间把整套规范翻了一遍,也在自己的试用环境里逐条验证过,今天就当是第十二…

2026/10/11 21:57:43 阅读更多 →
ruoyi 若依 自定义注解 参数校验

ruoyi 若依 自定义注解 参数校验

可以使用“枚举统一接口 自定义注解 ConstraintValidator”实现。你的项目是 Spring Boot 3&#xff0c;校验包应使用 jakarta.validation。1. 定义枚举统一接口package com.ruoyi.common.enums;/*** 具有业务编码的枚举。** param <T> 编码类型*/ public interface Co…

2026/10/11 21:57:43 阅读更多 →
GLinker 百万级实体链接:GLiNER 背后的知识图谱野心

GLinker 百万级实体链接:GLiNER 背后的知识图谱野心

GLinker 百万级实体链接&#xff1a;GLiNER 背后的知识图谱野心 【免费下载链接】gliner2.5-multi-v1 项目地址: https://ai.gitcode.com/hf_mirrors/fastino/gliner2.5-multi-v1 命名实体识别&#xff08;NER&#xff09;做到极致之后&#xff0c;下一步是什么&#x…

2026/10/11 21:57:43 阅读更多 →

最新新闻

MySQL子查询完全指南:分类、执行流程、性能优化与常见坑

MySQL子查询完全指南:分类、执行流程、性能优化与常见坑

子查询在MySQL里被很多人当成"会用但说不清"的技术点。SQL子查询用得好&#xff0c;能把复杂统计拆成清晰的嵌套逻辑&#xff1b;用不好&#xff0c;一条慢查询直接拖垮业务接口。这篇文章我把子查询从分类、执行流程到性能优化、报错排查完整过一遍&#xff0c;所有…

2026/10/11 22:51:36 阅读更多 →
手把手搭建中文RAG系统:从文档切片到本地大模型问答

手把手搭建中文RAG系统:从文档切片到本地大模型问答

1. 项目概述&#xff1a;这不是调用API&#xff0c;而是亲手搭一条“知识输送管道”你有没有试过这样一种场景&#xff1a;手头有一堆PDF、Word、Excel和内部Wiki文档&#xff0c;想让大模型准确回答“上季度华东区客户投诉TOP3原因是什么”&#xff0c;结果它要么胡编乱造&…

2026/10/11 22:51:36 阅读更多 →
LangGraph+MCP智能体工程方法论:可审计、可扩展、可运维的落地实践

LangGraph+MCP智能体工程方法论:可审计、可扩展、可运维的落地实践

1. 这不是又一个“AI Agent教程”&#xff0c;而是一套可落地的智能体工程方法论LangChain、LangGraph、MCP——这三个词最近在技术社区里出现的频率&#xff0c;已经快赶上“微服务”当年刚火起来时的状态了。但和当年不同的是&#xff0c;这次没有统一的架构图、没有成熟的部…

2026/10/11 22:51:36 阅读更多 →
LangChain+LangGraph+MCP智能体工程化实战方法论

LangChain+LangGraph+MCP智能体工程化实战方法论

1. 项目概述&#xff1a;这不是又一个“LangChain 教程”&#xff0c;而是一套可落地的智能体工程方法论你点开这个标题&#xff0c;大概率不是想学“怎么调用一个 LLM API”&#xff0c;而是被卡在了某个真实场景里&#xff1a;比如写了个自动处理客户工单的脚本&#xff0c;跑…

2026/10/11 22:51:36 阅读更多 →
YOLOv8手势识别实战:从训练到RK3588部署全链路

YOLOv8手势识别实战:从训练到RK3588部署全链路

简介&#xff1a;本资源是一个基于YOLOv8实现的手势识别完整应用项目&#xff0c;面向深度学习初学者与计算机视觉实践者&#xff0c;解决非接触式人机交互场景下的实时手势检测与识别问题&#xff0c;适用于智能交互、虚拟现实、辅助驾驶等方向的快速原型开发。压缩包共18个文…

2026/10/11 22:51:36 阅读更多 →
新浪Level2接口SDK接入实战:授权、协议解析与避坑指南

新浪Level2接口SDK接入实战:授权、协议解析与避坑指南

简介&#xff1a;新浪Level2接口SDK是一份面向量化开发与行情分析人员的Java工程&#xff0c;用于对接新浪Level2全推行情&#xff0c;获取股票、基金等品种的深度交易数据。相比普通免费接口&#xff0c;Level2数据在速度与深度上更适合机构级策略&#xff0c;适合有一定Java基…

2026/10/11 22:50:35 阅读更多 →

日新闻

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

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

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

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

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

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

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

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

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

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

周新闻

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

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

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

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

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

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

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

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

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#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/11 10:45:37 阅读更多 →
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/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练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/11 14:36:54 阅读更多 →