MediaPipe手语识别Python源码:LSTM/GRU时序分类与Gradio演示
简介这份资源是面向高校学生与Python初学者的手语识别毕业设计完整项目包基于MediaPipe实现静态与动态手势的检测与分类可用于毕业设计、期末大作业或计算机视觉入门实践。压缩包共21个文件约9.39MB包含5个Python源码文件分别负责静态手势检测、动态手势检测、数据集采集与Gradio可视化界面另有7张训练日志曲线图、1份requirements依赖清单、1份README说明文档以及LSTM与GRU两类动态模型和静态模型权重文件覆盖从数据采集、模型训练到界面演示的完整流程。目前已有378人学习下载。读者可直接运行源码复现手语识别效果借助训练日志图分析模型收敛情况参考依赖清单快速配置环境并基于现有模型结构进行二次开发或迁移到其他手势识别任务适合作为课程设计与入门项目的参考方案。1. 从一份能跑通的毕业设计说起mediapipe 手语识别到底交付了什么毕业季前两周实验室里最常见的一幕是有人抱着一个 zip 到处问「这个能不能直接跑」。手语识别这类题目尤其尴尬纯视觉方向听起来唬人真动手时又卡在数据采集、关键点提取、时序建模三座大山。这份基于 mediapipe 的手语识别 python 源码把静态手势和动态手势两条链路都做完了还附带了训练日志和已训练模型属于那种「下载完当天就能看到摄像头里出结果」的资源。它解决的核心问题不是算法有多新而是把 mediapipe 手部关键点提取、LSTM/GRU 时序分类、Gradio 网页演示这三段工程链路串成了一个闭环。适合两类人一类是毕业设计或期末大作业需要快速搭出可演示系统的同学另一类是刚接触 mediapipe 想找一个完整案例练手的 python 入门者。下面按「资源结构 → 数据采集 → 模型训练 → 推理演示 → 避坑」的顺序拆开讲每一步都落到能复现的命令和参数上。2. 拆开源码包GestureDetector 与两条识别链路的工程结构拿到压缩包先别急着 pip install花十分钟把目录结构看清楚后面调参和排错会省很多事。这份资源的组织方式很典型根目录放主流程脚本models 存权重logs 存训练曲线数据采集和推理演示各自独立成文件。理解这个分层才能知道改哪个文件会影响哪一段。2.1 静态与动态两条链路的文件分工静态手势识别走的是「单帧关键点 → 分类」的路子对应static_hand_detect.py和static_model_lstm_126。动态手势识别需要连续帧走的是「多帧序列 → LSTM/GRU → 分类」对应dynamic_hand_detect.py和dynamic_model_lstm_258、dynamic_model_gru_1662等一组权重。GestureDetector是公共模块封装了 mediapipe 的 Hands 解决方案静态和动态脚本都调用它所以关键点提取逻辑只维护一份。get_static_dataset.py和get_dynamic_dataset.py分别负责采集两类数据。前者按单帧保存关键点后者按时间窗口保存序列。gradio_app.py是网页演示入口把摄像头或上传视频接进来做实时推理。requirements.txt锁依赖README.md写基本说明。models 目录下的命名规则值得注意dynamic_model_lstm_258里的 258 通常指序列长度或特征维度dynamic_model_gru_1662里的 1662 是另一组超参训练日志 png 和模型文件一一对应方便你对照曲线判断哪组权重更稳。2.2 依赖安装与 mediapipe 版本对齐mediapipe 的安装是这份资源第一个容易翻车的地方。它对新版 python 和 numpy 比较挑常见做法是建一个干净虚拟环境把 python 固定在 3.8 到 3.10 之间。下面这套命令我一般会先跑一遍确认环境干净# 建虚拟环境python 版本建议 3.8~3.10 python -m venv venv # Windows 激活 venv\Scripts\activate # Linux / macOS 激活 source venv/bin/activate # 先升级 pip避免旧 pip 解析依赖失败 python -m pip install --upgrade pip # 按 requirements 安装mediapipe 版本以文件里锁定的为准 pip install -r requirements.txt逻辑说明虚拟环境隔离是为了避免和系统里已有的 opencv、numpy 冲突mediapipe 对 numpy 版本敏感混装很容易出现ImportError: cannot import name ...。参数说明如果requirements.txt里没锁 mediapipe 版本我一般会装mediapipe0.10.x这一档太新的版本 API 偶有变动太旧的又缺 Hands 的某些参数。安装完先跑一句验证import mediapipe as mp import cv2 print(mp.__version__) print(cv2.__version__)能打印出版本号且不报错说明基础环境通了。如果这里就报DLL load failed多半是 Visual C 运行库缺失装一下微软的 VC redistributable 即可这属于环境问题不是代码问题。2.3 关键点提取GestureDetector 里真正要关注的参数GestureDetector封装的核心是 mediapipe Hands 的几个参数这些参数直接决定识别稳不稳。常见配置是max_num_hands1、min_detection_confidence0.5、min_tracking_confidence0.5。手语识别一般单手为主max_num_hands设 1 能减少误检检测置信度设太低会把手部背景噪声也框进来设太高又容易丢帧。关键点输出是 21 个手部 landmark每个点有 x、y、z 三个坐标展平后是 63 维。静态模型输入就是这 63 维动态模型输入是若干帧的 63 维拼成的序列。这里有个容易忽略的点mediapipe 输出的坐标是归一化到 0 到 1 的如果训练和推理时归一化方式不一致模型表现会断崖式下降。所以采集数据和推理必须共用同一个 GestureDetector这也是为什么它被抽成公共模块。3. 数据采集与模型训练从 get_dataset 脚本到 LSTM/GRU 权重很多人拿到源码直接跑推理发现识别不准根因往往在数据采集阶段就埋下了。手语识别的数据质量比模型结构重要得多这一章把采集和训练两段讲透你才能自己补数据、重训模型而不是只能用它给的权重。3.1 静态数据集采集单帧关键点的保存格式get_static_dataset.py的典型流程是打开摄像头按键触发采集把当前帧的 21 个关键点存成一条样本同时记录类别标签。常见做法是每个类别采 100 到 200 条太少模型学不动太多又容易过拟合到某个人的手型。下面是一段采集逻辑的示意import cv2 import numpy as np from GestureDetector import GestureDetector detector GestureDetector() cap cv2.VideoCapture(0) samples, labels [], [] current_label 0 # 当前采集的类别编号 while True: ret, frame cap.read() if not ret: break # 提取手部关键点返回 63 维向量或 None keypoints detector.extract_keypoints(frame) if keypoints is not None: samples.append(keypoints) labels.append(current_label) cv2.imshow(collect, frame) key cv2.waitKey(1) 0xFF if key ord(q): break elif key ord(n): current_label 1 # 切换到下一个类别 np.save(static_samples.npy, np.array(samples)) np.save(static_labels.npy, np.array(labels))逻辑说明extract_keypoints内部调用 mediapipe返回展平后的 63 维向量检测不到手时返回 None所以采集时要判断非空再存。参数说明current_label用按键切换保证每个类别样本连续采集保存成 npy 方便后续直接np.load读入训练脚本。注意采集时手要在画面里多变换角度和距离否则模型只认一种姿态演示时稍微偏一点就识别错。3.2 动态数据集采集时间窗口与序列长度动态手势的关键是时间维度。get_dynamic_dataset.py一般会维护一个固定长度的队列比如 30 帧每帧存 63 维凑满一个窗口就作为一条序列样本。序列长度这个参数很关键太短捕捉不到动作过程太长会引入冗余帧拖慢训练。资源里模型名带 258 和 1662很可能对应不同的序列长度或特征拼接方式训练日志 png 能帮你判断哪组收敛更好。from collections import deque import numpy as np SEQ_LEN 30 # 序列长度对应模型输入的时间步 buffer deque(maxlenSEQ_LEN) sequences, seq_labels [], [] # 在采集循环里每帧提取关键点后 if keypoints is not None: buffer.append(keypoints) # 队列满且按下采集键时存一条序列 if len(buffer) SEQ_LEN and trigger_collect: sequences.append(np.array(buffer)) seq_labels.append(current_label) buffer.clear()逻辑说明deque(maxlenSEQ_LEN)自动丢弃最旧的帧保证窗口滑动。参数说明SEQ_LEN要和训练脚本里的输入维度对齐改了这个值必须同步改模型输入层否则会报 shape 不匹配。采集动态数据时动作要完整做完再触发保存半截动作会让标签和序列对不上这是血泪经验。3.3 训练脚本与日志解读LSTM 和 GRU 怎么选训练部分资源里给了 LSTM 和 GRU 两组权重说明作者做过对比。LSTM 参数多、表达能力强适合动作类别多、区分度细的场景GRU 参数少、训练快在小数据集上反而不容易过拟合。logs 目录下的 png 是训练曲线看两条线训练 loss 和验证 loss。如果验证 loss 早早回升说明过拟合该加 dropout 或减层如果两条都居高不下说明欠拟合该加数据或加容量。from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, GRU, Dense, Dropout def build_lstm(input_shape, num_classes): model Sequential([ LSTM(64, return_sequencesTrue, input_shapeinput_shape), Dropout(0.3), LSTM(32), Dense(64, activationrelu), Dense(num_classes, activationsoftmax) ]) model.compile(optimizeradam, losscategorical_crossentropy, metrics[accuracy]) return model逻辑说明两层 LSTM 逐层降维dropout 抑制过拟合最后 softmax 输出类别概率。参数说明input_shape是(SEQ_LEN, 63)num_classes是你实际的手语类别数必须和标签编码一致。训练时把数据按 8:2 切训练验证集batch size 一般 16 或 32epoch 看验证 loss 不再下降就停。资源里已训练好的权重可以直接加载但如果你想加自己的手势类别就得重新采集并重训不能只改输出层。4. 推理与 Gradio 演示把模型接到摄像头和网页上训练完只是半成品能演示才算交付。这一章讲推理脚本怎么跑、Gradio 网页怎么起以及实时推理时延迟和抖动的处理。很多人卡在「模型准确率挺高但演示时一顿一顿」问题基本出在推理循环和帧处理上。4.1 静态推理static_hand_detect.py 的实时循环静态推理脚本的逻辑是读摄像头帧、提关键点、喂模型、显示结果。核心是把模型加载一次放在循环外循环内只做前向推理否则每帧都加载模型会慢到没法看。import cv2 import numpy as np from tensorflow.keras.models import load_model from GestureDetector import GestureDetector model load_model(models/static_model_lstm_126) detector GestureDetector() cap cv2.VideoCapture(0) while True: ret, frame cap.read() if not ret: break keypoints detector.extract_keypoints(frame) if keypoints is not None: # 模型输入需要 batch 维度扩展成 (1, 63) pred model.predict(np.expand_dims(keypoints, axis0), verbose0) label np.argmax(pred) cv2.putText(frame, flabel: {label}, (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) cv2.imshow(static, frame) if cv2.waitKey(1) 0xFF ord(q): break逻辑说明np.expand_dims补上 batch 维度因为 Keras 模型默认接受批量输入。参数说明verbose0关掉每帧的预测日志否则控制台会刷屏拖慢速度。如果画面卡顿把摄像头分辨率降到 640x480mediapipe 在低分辨率下检测速度明显更快。4.2 动态推理序列缓冲与预测时机动态推理比静态复杂因为要攒够 SEQ_LEN 帧才能预测一次。常见做法是维护一个滑动窗口每来一帧就更新窗口窗口满时推理一次并显示结果。这里有个取舍每帧都推理会抖动隔几帧推理一次又延迟大。我一般会设一个预测间隔比如每 5 帧推理一次兼顾流畅和稳定。from collections import deque SEQ_LEN 30 buffer deque(maxlenSEQ_LEN) frame_count 0 while True: ret, frame cap.read() if not ret: break keypoints detector.extract_keypoints(frame) if keypoints is not None: buffer.append(keypoints) frame_count 1 # 窗口满且到达预测间隔才推理 if len(buffer) SEQ_LEN and frame_count % 5 0: seq np.expand_dims(np.array(buffer), axis0) pred model.predict(seq, verbose0) label np.argmax(pred) cv2.putText(frame, faction: {label}, (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) cv2.imshow(dynamic, frame) if cv2.waitKey(1) 0xFF ord(q): break逻辑说明buffer始终保留最近 SEQ_LEN 帧frame_count % 5控制推理频率。参数说明预测间隔根据机器性能调性能好可以设 3性能差设 10。注意 buffer 在检测不到手时不要清空否则动作中间丢帧会导致序列断裂识别直接失效。4.3 Gradio 网页演示gradio_app.py 的启动与端口gradio_app.py把推理包装成网页界面适合答辩演示时不用装摄像头驱动。启动方式一般是直接跑脚本Gradio 会自动起一个本地服务并打印地址。# 启动 Gradio 演示默认端口 7860 python gradio_app.py # 如果端口被占用可以指定端口 python gradio_app.py --server_port 7861逻辑说明Gradio 默认监听 127.0.0.1:7860浏览器打开打印出的地址即可。参数说明如果脚本里写死了shareFalse就只能本机访问答辩时如果需要同局域网访问把launch参数里的server_name设成0.0.0.0。注意 Gradio 版本和脚本里的 API 要对齐老版本用gr.Interface新版本部分参数有变动报错时先看requirements.txt锁的版本。5. 避坑与排查mediapipe 手语识别最常见的五个翻车点这一章是我自己踩过和帮别人排过的坑按「现象 → 原因 → 解决」写。手语识别这类项目代码本身往往没问题翻车基本集中在环境、数据和参数对齐上。5.1 现象mediapipe 导入报错或 Hands 初始化失败原因python 版本过高或 numpy 版本冲突mediapipe 对 3.11 以上支持不稳定numpy 2.x 也常和旧版 mediapipe 不兼容。解决把 python 降到 3.8 到 3.10numpy 锁到 1.24 以下重建虚拟环境后重装。别在系统 python 里硬修越修越乱。5.2 现象摄像头能开但关键点一直检测不到原因min_detection_confidence设太高或者光照太暗、手离镜头太远。解决先把置信度降到 0.3 测试确认能检测到再逐步调回 0.5同时保证手在画面中央、光线均匀。如果还是不行检查摄像头帧是不是 BGR 格式mediapipe 需要 RGB常见做法是cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)后再传入。5.3 现象模型预测结果全是同一个类别原因训练时标签编码和推理时不一致或者归一化方式不同。解决确认训练和推理共用同一个 GestureDetector标签映射表要一致。如果重训过模型检查num_classes和实际类别数是否匹配输出层维度错了会直接导致预测塌缩。5.4 现象动态识别延迟高、画面卡顿原因每帧都跑模型推理或者序列长度设太大。解决降低推理频率用frame_count % N控制把 SEQ_LEN 从 30 降到 20 试试延迟会明显下降。另外摄像头分辨率降到 640x480mediapipe 的检测耗时和分辨率强相关。5.5 现象Gradio 网页打不开或上传视频无响应原因端口被占用或者 Gradio 版本和脚本 API 不匹配。解决换端口启动报错信息里通常会提示哪个参数不对。上传视频无响应多半是视频解码问题opencv 对某些编码格式支持不好转成 mp4 的 H.264 再试。6. 进阶技巧用已训练权重做迁移快速加自己的手势类别资源里给的权重不是终点而是起点。答辩时如果只演示作者预设的几个手势容易被问「能不能加一个」。这时候不用从头采集重训可以用已训练模型做特征提取只重训最后的分类层几十条样本就能出一个新类别。具体做法是加载模型去掉最后一层 Dense把前面层的输出当特征冻结权重只训练新的分类头。from tensorflow.keras.models import load_model, Model from tensorflow.keras.layers import Dense import numpy as np # 加载已训练模型去掉最后的分类层 base load_model(models/dynamic_model_lstm_258) feature_model Model(inputsbase.input, outputsbase.layers[-2].output) # 冻结特征提取层 for layer in feature_model.layers: layer.trainable False # 在新数据上提取特征只训练新的分类头 new_head Dense(5, activationsoftmax) # 假设新增到 5 类 # 用 feature_model.predict 得到特征后接 new_head 训练若干轮逻辑说明冻结底层是为了防止小样本把已学到的关键点特征带偏只让分类头适应新类别。参数说明新类别样本每个采 30 到 50 条即可太多反而过拟合训练轮数控制在 20 以内看验证准确率不再涨就停。这套迁移思路同样适用于把静态模型改成动态只要输入维度对齐。验证迁移效果时我习惯留出 20% 新样本做测试准确率能到 85% 以上就算可用。如果低于 70%多半是新类别和旧类别动作太像得重新设计手势或增加样本多样性。从那以后我每次加新类别都强制走一遍「采集 → 提特征 → 只训分类头 → 留出验证」的流程不再盲目重训整个模型。希望这份拆解能帮你少走几个弯路把这份毕业设计真正用起来。本文还有配套的精品资源点击获取

相关新闻

光伏板数据集labelimg标注xml转YOLOv8训练全流程与避坑指南

光伏板数据集labelimg标注xml转YOLOv8训练全流程与避坑指南

简介:这是一份面向光伏板检测与计算机视觉方向研究者的标注数据集,适合从事目标检测模型训练、算法对比与新能源监测应用的开发者使用。数据采集完成后借助labelimg逐张绘制边界框,每张图片均配有对应的xml标注文件,记录光伏板坐标…

2026/10/10 6:32:56 阅读更多 →
合规调用Claude与Vertex AI:LLM外部工具集成实战指南

合规调用Claude与Vertex AI:LLM外部工具集成实战指南

我不能按照该标题生成内容,原因如下:标题中提及的“Google Antigravity”并非真实存在的 Google 官方服务或产品,属于虚构名称(Google 官方从未发布、命名或公开任何名为 “Antigravity” 的技术、API、模型或平台)。在…

2026/10/10 6:32:56 阅读更多 →
麦田物语课程设计:Phaser3与TypeScript构建作物状态机与季节系统

麦田物语课程设计:Phaser3与TypeScript构建作物状态机与季节系统

简介:面向高校游戏开发、数字媒体技术等专业的课程设计与毕业设计需求,这套基于麦田物语主题的项目资源包,提供了从场景搭建到角色动画的一体化参考方案,可有效解决同类课设中项目结构混乱、素材不完整、动画状态机配置困难等问题…

2026/10/10 6:31:56 阅读更多 →

最新新闻

macOS上QQ音乐QMC格式转换:qmcflac转flac、qmc0转mp3

macOS上QQ音乐QMC格式转换:qmcflac转flac、qmc0转mp3

简介:这是一份面向macOS用户的QQ音乐QMC格式转换工具源码包,可将qmcflac、mflac等格式还原为flac,将qmc0、qmc3等转为mp3,解决客户端加密音频无法在其他播放器中直接使用的痛点。项目基于Swift开发,完整Xcode工程可直接…

2026/10/10 7:43:29 阅读更多 →
碳中和软件测试怎么做:用AI量化碳排放,把环保变成CI/CD拦截关卡

碳中和软件测试怎么做:用AI量化碳排放,把环保变成CI/CD拦截关卡

提到碳中和,大多数人先想到的可能是工厂烟囱、燃油车尾气,很少有人会往软件身上想。但真开始做碳中和软件测试之后,我发现软件的能耗和碳排放比想象中要棘手得多:一次API调用背后的CPU、内存、磁盘和网络,每一层都在烧…

2026/10/10 7:43:29 阅读更多 →
Mac上QMC格式转换:qmcflac/mflac解密还原flac与mp3实战

Mac上QMC格式转换:qmcflac/mflac解密还原flac与mp3实战

简介:面向macOS用户的QQ音乐QMC格式转码工具,能将qmcflac转为flac、qmc0/qmc3转为mp3,并支持mflac、mflac0等变体转flac,附带完整源码与Xcode工程配置。它解决QQ音乐加密音频无法在普通播放器直接使用的问题,适合音频处…

2026/10/10 7:43:29 阅读更多 →
Spring Boot学生成绩管理系统源码部署与毕设避坑指南

Spring Boot学生成绩管理系统源码部署与毕设避坑指南

拿这套Springboot学生成绩管理系统的时候,我的第一反应不是看代码写了多少,而是先确认一件事:能不能在半小时内从零跑起来。很多同类项目源码写得再花哨,环境配不平、数据库导不进、端口起不来,基本就废了。这套系统8w…

2026/10/10 7:43:28 阅读更多 →
ProtoBuf自定义反序列化实战:从二进制格式到手写解析器

ProtoBuf自定义反序列化实战:从二进制格式到手写解析器

去年维护一个老网关的时候,我需要把一个从 TCP 连接里收到的裸字节数组,直接还原成 ProtoBuf 消息对象。当时项目里有个公共依赖没升级,标准parseFrom用不了,数据格式又没法改,只能在拿到字节数组后自己写反序列化逻辑…

2026/10/10 7:43:28 阅读更多 →
搞了三天才明白,Vue这个特性根本不是这样用的

搞了三天才明白,Vue这个特性根本不是这样用的

上周五凌晨,我盯着屏幕上疯狂抖动的图表组件,看着内存占用曲线像过山车一样攀升,终于意识到自己掉进了v-if和v-for的死亡组合陷阱。这个在代码审查时被轻飘飘放过的"小问题",让我们的实时监控系统在万级数据量下直接崩溃…

2026/10/10 7:42:28 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* 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 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

月新闻

我发现了一个新思路:用 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/9 6:17:20 阅读更多 →