HOG+SVM实战:从特征提取到滑窗检测的完整指南
简介本资源是一套基于HOG特征与SVM分类器的手写字符识别完整工程方案面向计算机视觉入门者、模式识别课程学习者及需要完成相关实验或课程设计的学生。方案以CASIA-NLPR手写字符数据集为处理对象涵盖特征提取、模型训练与分类预测的完整流程适合具备一定C基础、希望理解传统机器学习图像分类思路的读者参考。压缩包共21个文件以h头文件与cpp源文件为核心配合vcxproj工程文件、filters筛选配置及sln解决方案文件整体约39KB结构精简可直接在Visual Studio中打开编译。工程按Task1、HWDB、OLHWDB等模块组织分别对应不同数据集的处理任务便于读者对照理解各模块职责与调用关系。目前已有131人学习下载可作为HOGSVM实战练手的参考模板帮助读者快速搭建实验环境、梳理特征提取与分类器训练的关键环节。1. 从一份“HOGSVM”方案说起它到底能解决什么识别问题如果你手头有一批标注好的小样本图像想做一个不依赖深度学习框架、能在普通 CPU 上跑起来的分类器HOG 特征加 SVM 分类器这套组合大概率会被反复提起。它最经典的应用场景就是行人检测把图像切成小窗口用方向梯度直方图描述边缘和纹理的分布再交给支持向量机判断“是人”还是“不是人”。这套方案不追求 SOTA但胜在原理透明、训练快、可解释性强特别适合嵌入式设备、工业质检、教学复现以及作为深度学习之前的 baseline。我见过不少团队在项目初期用 HOGSVM 快速验证数据是否可分再决定要不要上卷积网络。它的门槛不在数学而在工程细节窗口怎么滑、block 怎么归一化、正负样本怎么配比、SVM 的 C 和 gamma 怎么调。这些参数一旦设错准确率能从 95% 掉到 70%而且很难从代码里一眼看出问题。接下来我会按“特征提取 → 分类器训练 → 滑窗检测 → 调参排坑”的顺序把这条链路拆成能直接抄作业的步骤。2. HOG 特征提取从像素到梯度直方图的完整链路2.1 为什么 HOG 对光照和形变比原始像素更稳HOG 的核心思想是局部区域的边缘方向分布比单个像素值更能代表物体形状。它先把图像灰度化再用 Gamma 校正压缩动态范围然后计算每个像素的水平梯度和垂直梯度得到梯度幅值和方向。接着把图像划分成 8×8 的 cell每个 cell 内按 9 个方向 bin 做加权投票得到一个 9 维直方图。最后把相邻的 2×2 个 cell 组成一个 block对 block 内 36 维向量做 L2 归一化。这个流程里Gamma 校正和 block 归一化是抗光照变化的关键。没有它们同一物体在明暗不同的区域会得到完全不同的特征向量。而 cell 和 block 的尺寸决定了特征的粒度cell 越小对细节越敏感但噪声也越大block 越大归一化范围越广但会平滑掉局部差异。常见做法是 cell 取 8×8block 取 2×2窗口取 64×128这个配置在行人检测上被验证过很多次。2.2 用 OpenCV 提取 HOG 特征的最小代码下面这段代码展示了如何用 OpenCV 的 HOGDescriptor 提取一张图像的 HOG 特征。注意参数要和训练时保持一致否则特征维度对不上。import cv2 import numpy as np # 读取图像并统一尺寸HOG 对输入尺寸敏感 img cv2.imread(sample.jpg) img cv2.resize(img, (64, 128)) # 窗口大小 64x128 # 定义 HOG 描述子 hog cv2.HOGDescriptor( _winSize(64, 128), # 检测窗口大小 _blockSize(16, 16), # 2x2 个 cell _blockStride(8, 8), # block 滑动步长 _cellSize(8, 8), # 每个 cell 8x8 像素 _nbins9 # 9 个方向 bin ) # 计算特征向量维度为 3780 features hog.compute(img) print(features.shape) # (3780, 1)逻辑说明_winSize必须和你的目标物体在图像中的实际尺寸匹配。如果目标在图中占 128×256你硬缩到 64×128边缘信息会丢失。_blockStride一般取 cellSize 的一半或相等步长越小特征越密但计算量越大。_nbins取 9 是经验值对应 0 到 180 度每 20 度一个 bin。输出的 3780 维向量就是 SVM 的输入。参数调整建议如果目标纹理细密可以把 cellSize 降到 4×4但特征维度会涨到 15000 以上训练时间明显增加。如果目标轮廓简单cellSize 可以升到 16×16维度降到 900 左右适合快速实验。2.3 正负样本的采集与尺寸归一化HOGSVM 是监督学习正负样本的质量直接决定上限。正样本要尽量覆盖目标的不同姿态、光照和遮挡情况负样本要包含容易混淆的背景区域。常见做法是正样本每类不少于 500 张负样本是正样本的 2 到 3 倍。所有样本必须缩放到同一个窗口尺寸比如 64×128。我一般会写一个脚本批量处理正样本从标注框里裁剪出来负样本从没有目标的区域随机裁剪然后统一 resize 并保存为灰度图。注意不要对负样本做过度筛选否则模型会过拟合到特定背景。另外样本的宽高比要一致否则 HOG 特征会引入形变噪声。3. SVM 分类器训练参数、核函数与样本配比3.1 线性核还是 RBF 核先看特征维度和样本量HOG 特征维度通常几千维样本量几百到几千。这种情况下线性核往往就够了因为高维空间里数据更容易线性可分而且线性核训练快、不容易过拟合。RBF 核适合特征维度低、样本量中等且分布复杂的场景但它多了 gamma 参数调参成本高。我的经验是先跑线性核如果验证集准确率明显低于训练集再考虑 RBF。在 sklearn 里SVC(kernellinear)和SVC(kernelrbf)的接口一样但训练时间差很多。线性核在 5000 维、2000 样本上通常几秒到几十秒RBF 可能要几分钟。如果只是验证方案可行性线性核是更务实的选择。3.2 用 sklearn 训练 HOGSVM 的完整脚本下面这段代码把特征提取和 SVM 训练串起来包含数据加载、特征拼接、训练和保存模型。import os import cv2 import numpy as np from sklearn.svm import SVC from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score import joblib # HOG 参数与前面保持一致 hog cv2.HOGDescriptor( _winSize(64, 128), _blockSize(16, 16), _blockStride(8, 8), _cellSize(8, 8), _nbins9 ) def load_features(pos_dir, neg_dir): X, y [], [] for label, folder in [(1, pos_dir), (0, neg_dir)]: for fname in os.listdir(folder): path os.path.join(folder, fname) img cv2.imread(path, cv2.IMREAD_GRAYSCALE) if img is None: continue img cv2.resize(img, (64, 128)) feat hog.compute(img).flatten() X.append(feat) y.append(label) return np.array(X), np.array(y) X, y load_features(data/pos, data/neg) X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) # 线性核 SVMC 控制惩罚力度 clf SVC(kernellinear, C1.0, probabilityTrue) clf.fit(X_train, y_train) y_pred clf.predict(X_test) print(准确率:, accuracy_score(y_test, y_pred)) # 保存模型和 HOG 参数推理时要复用 joblib.dump(clf, hog_svm_model.pkl)逻辑说明stratifyy保证训练集和测试集的正负比例一致避免某类样本被抽空。probabilityTrue会启用概率输出但会拖慢训练速度如果只做硬分类可以关掉。C是惩罚系数C 越大对误分类容忍度越低容易过拟合C 越小则更宽容可能欠拟合。一般从 0.1、1、10 里试。参数说明joblib.dump保存的是训练好的 SVM 模型但 HOG 参数没有存进去。推理时你必须用同样的_winSize、_blockSize等参数重新构造 HOGDescriptor否则特征维度对不上。我习惯把 HOG 参数写进一个配置文件训练和推理都读同一份。3.3 样本不均衡时用 class_weight 还是重采样实际项目里负样本往往远多于正样本比如行人检测中背景窗口是行人的几十倍。这时候 SVM 会偏向多数类导致正样本召回率很低。两种处理方式一是设置class_weightbalanced让 SVM 自动按类别频率调整权重二是对正样本过采样或对负样本欠采样。我一般先用 class_weight因为它不改变数据分布只是调整损失函数的惩罚力度。如果效果不够再对负样本做随机欠采样但要注意别丢掉太多背景多样性。4. 滑窗检测与 NMS把分类器变成检测器的关键一步4.1 多尺度滑窗为什么固定窗口不够用训练好的 SVM 只能判断一个固定尺寸的窗口里有没有目标。但实际图像中目标大小不一所以需要多尺度滑窗把图像按不同比例缩放在每个尺度上用固定窗口滑动收集所有被判定为正的窗口。常见做法是缩放因子取 1.05 到 1.2尺度从大到小或从小到大都行。每个尺度上窗口步长可以取窗口宽高的 1/8 到 1/4步长越小检测越密但计算量越大。滑窗会产生大量重叠框同一个目标可能被检测到几十次。这时候就需要非极大值抑制NMS来合并。NMS 的逻辑是按置信度排序保留最高分框然后删掉与它 IoU 超过阈值的其他框。IoU 阈值一般取 0.3 到 0.5阈值越低合并越激进可能漏掉相邻目标阈值越高保留框越多可能重复。4.2 滑窗检测与 NMS 的代码实现下面这段代码展示了从多尺度滑窗到 NMS 的完整流程可以直接套用到你的检测任务上。import cv2 import numpy as np import joblib clf joblib.load(hog_svm_model.pkl) hog cv2.HOGDescriptor( _winSize(64, 128), _blockSize(16, 16), _blockStride(8, 8), _cellSize(8, 8), _nbins9 ) def detect(img, scale1.05, step_ratio0.2, score_thresh0.5): boxes, scores [], [] h, w img.shape[:2] cur_scale 1.0 while cur_scale 0.3: # 最小尺度限制 resized cv2.resize(img, (int(w * cur_scale), int(h * cur_scale))) rh, rw resized.shape[:2] step_y int(128 * step_ratio) step_x int(64 * step_ratio) for y in range(0, rh - 128, step_y): for x in range(0, rw - 64, step_x): patch resized[y:y128, x:x64] feat hog.compute(patch).flatten().reshape(1, -1) score clf.predict_proba(feat)[0][1] if score score_thresh: # 映射回原图坐标 boxes.append([int(x/cur_scale), int(y/cur_scale), int(64/cur_scale), int(128/cur_scale)]) scores.append(score) cur_scale / scale # NMS idx cv2.dnn.NMSBoxes(boxes, scores, score_thresh, 0.4) return [boxes[i] for i in idx], [scores[i] for i in idx]逻辑说明scale控制金字塔层数1.05 意味着每层缩小 5%层数多但检测更细。step_ratio是滑窗步长占窗口尺寸的比例0.2 表示每次移动 20% 窗口宽高。score_thresh过滤低置信度框太低会引入大量误检太高会漏检。NMS 的 IoU 阈值设为 0.4这是行人检测里比较常用的值。参数说明cur_scale 0.3是防止图像被缩得太小导致目标消失。如果你的目标在图中占比很小可以把下限调到 0.1。cv2.dnn.NMSBoxes要求 boxes 格式为[x, y, w, h]返回的是保留框的索引。注意这个函数在不同 OpenCV 版本里返回值类型可能不同有的返回二维数组取索引时要小心。4.3 检测阶段最耗时的环节与优化方向滑窗检测的计算量主要花在 HOG 特征计算和 SVM 预测上。一张 640×480 的图如果做 10 层金字塔每层滑几千个窗口总窗口数可能上万。每个窗口都要算 3780 维 HOG 特征再送进 SVMCPU 上跑一次检测可能要几秒到几十秒。优化方向有三个一是减少金字塔层数只保留目标可能出现的尺度二是增大滑窗步长牺牲召回换速度三是用线性 SVM 的权重向量和 HOG 特征做点积避免 sklearn 的预测开销。我一般先跑通流程再根据实际帧率要求调这三个参数。5. 避坑与排查HOGSVM 落地时最容易翻车的五个地方5.1 准确率虚高但实际检测全是误检现象训练时验证集准确率 98%但拿真实图片做滑窗检测满屏都是框。原因负样本采集过于单一模型没学过真实背景的多样性。训练时的负样本可能只来自少数几张图而实际场景背景千变万化。解决负样本要覆盖各种背景最好从实际检测场景里随机裁剪数量至少是正样本的 2 倍。另外可以加入难例挖掘用初始模型跑一遍训练图把误检的窗口加入负样本重新训练。5.2 特征维度对不上导致推理报错现象训练完保存模型推理时clf.predict报错提示特征维度不一致。原因训练和推理用的 HOG 参数不同比如训练时_winSize(64,128)推理时图像 resize 成了(128,64)或者_cellSize改了。解决把 HOG 参数写进配置文件训练和推理都从同一份配置读取。保存模型时顺便把参数一起存加载时先恢复参数再构造 HOGDescriptor。5.3 正样本标注框比例不一致引入形变噪声现象模型对某些姿态的目标检测效果特别差。原因正样本裁剪时没有统一宽高比有的框是正方形有的框是细长条resize 到 64×128 后目标被拉伸变形HOG 特征学到的形状是扭曲的。解决裁剪正样本时保持原始宽高比用 padding 补到统一尺寸而不是直接 resize。如果目标本身宽高比变化大可以考虑按宽高比分组训练多个模型。5.4 SVM 的 C 值设太大导致过拟合现象训练集准确率接近 100%测试集只有 70% 多。原因C 值太大SVM 对每个误分类样本都严厉惩罚导致决策边界过度拟合训练数据。解决把 C 从 1 降到 0.01 到 0.1 之间试同时观察训练集和测试集准确率的差距。如果差距缩小但测试集没提升可能是特征本身区分度不够需要回到 HOG 参数调整。5.5 NMS 阈值设错导致相邻目标被合并现象两个靠得很近的目标只检测出一个框。原因NMS 的 IoU 阈值设得太低比如 0.3两个目标的框重叠度超过 0.3 就被合并了。解决把 IoU 阈值提高到 0.5 或 0.6让重叠度高的框保留下来。如果目标确实密集可以考虑用 Soft-NMS按重叠度衰减分数而不是直接删除。6. 进阶技巧用难例挖掘和特征降维把准确率再提一截6.1 难例挖掘的迭代流程难例挖掘是提升 HOGSVM 检测效果最实用的技巧。具体做法先用初始模型在训练集上跑滑窗检测收集所有误检的窗口被判定为正但实际是背景把这些窗口加入负样本集重新训练。重复两到三轮模型对困难背景的区分能力会明显增强。注意每轮加入的难例不要太多否则负样本分布会过度偏向某些背景导致其他场景误检增加。我一般每轮加入误检窗口的 50% 到 70%保留一部分随机性。6.2 用 PCA 降维压缩 HOG 特征HOG 特征 3780 维里有很多冗余用 PCA 降到 200 到 500 维可以大幅加快 SVM 训练和推理速度同时可能提升泛化能力。做法是在训练集上拟合 PCA保留 95% 到 99% 的方差然后把训练集和测试集都投影到低维空间。注意 PCA 的均值向量和投影矩阵要保存下来推理时对新特征做同样的变换。降维后 SVM 的 C 值可能需要重新调因为特征尺度变了。from sklearn.decomposition import PCA from sklearn.pipeline import Pipeline pipe Pipeline([ (pca, PCA(n_components0.99)), # 保留 99% 方差 (svm, SVC(kernellinear, C0.5)) ]) pipe.fit(X_train, y_train)逻辑说明n_components0.99表示自动选择能解释 99% 方差的主成分数量通常比手动指定更稳。Pipeline 把 PCA 和 SVM 串起来保存时用joblib.dump(pipe, ...)推理时直接pipe.predict不用手动做投影。注意 PCA 必须在训练集上拟合不能在全量数据上拟合否则会引入测试集信息。6.3 一个容易被忽略的细节HOG 的 Gamma 校正OpenCV 的 HOGDescriptor 默认不做 Gamma 校正但很多论文里 Gamma 校正是标准步骤。如果你的图像明暗差异大可以手动加一步 Gamma 变换把像素值压缩到 0 到 1 之间再开方。这一步对夜间或逆光场景的提升比较明显。我一般会在预处理阶段统一做而不是依赖 HOGDescriptor 的内部实现。最后说个我自己的习惯每次调完参数我都会把训练集和测试集的准确率、召回率、误检率记在一个表格里标注当时的 HOG 参数和 SVM 参数。这样下次遇到类似数据能快速定位到可用的参数区间不用从头试。HOGSVM 这套东西参数不多但组合起来变化不少有记录才能少走弯路。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Frank-Wolfe求解交通用户均衡:SiouxFalls网络实战解析

Frank-Wolfe求解交通用户均衡:SiouxFalls网络实战解析

简介:本资源是一份面向交通工程、运筹优化与智能交通系统方向的Python实践代码包,聚焦用户均衡(UE)问题的算法实现与小规模网络验证,适合交通规划初学者、研究生课程设计及算法爱好者动手复现。资源采用经典Frank-Wolf…

2026/10/13 16:36:05 阅读更多 →
从grep到rea:命令行日志分析工具的字段提取实践

从grep到rea:命令行日志分析工具的字段提取实践

半夜两点,我对着一个 1.8GB 的访问日志发呆。我要在几十万条请求里,把某次超时链路涉及的所有记录捞出来,按请求 ID 拼成完整时间线,再看哪个环节耗时异常。第一反应是 grep,grep 也确实把行筛出来了,但筛完…

2026/10/13 16:35:03 阅读更多 →
知识工作插件全解析:从需求到落地的效率提升指南

知识工作插件全解析:从需求到落地的效率提升指南

1. 为什么我盯上了"knowledge-work-plugins"这组关键词先坦白一下我的习惯:平时逛代码仓库、刷技术社区时,我不太喜欢追那种名字特别花哨的项目,反而会对那种一眼看上去就是个"生产力工具集合"的仓库格外来劲。前几天看到…

2026/10/13 16:35:03 阅读更多 →

最新新闻

金字塔原理:职场沟通结构化表达的四个原则与实战技巧

金字塔原理:职场沟通结构化表达的四个原则与实战技巧

废话不多说,这可能是你在职场沟通中最值得补的一课。我见过太多人,明明业务能力很强,可一开口就败下阵来:汇报讲了十分钟,领导眉头越皱越紧;邮件写了几百字,对方回复“所以你想表达什么”&#…

2026/10/13 17:10:09 阅读更多 →
实时数据采集架构设计:从需求量化到全链路调优

实时数据采集架构设计:从需求量化到全链路调优

直接开讲。实时数据采集架构设计这件事,我前前后后做了三年多,从最早只会写脚本定时拉数据,到后来能独立设计一套覆盖采集、缓冲、计算、落库全链路的实时方案,中间踩过不少坑。很多人一听到“实时数据采集”这几个字,…

2026/10/13 17:10:09 阅读更多 →
专科生AI论文写作平台实测:8个靠谱工具全解析

专科生AI论文写作平台实测:8个靠谱工具全解析

实话实说,专科生写毕业论文,难度不比本科生低,甚至更难。难在哪?时间紧、任务重,还有相当一部分同学是第一次接触完整的学术写作流程。我自己当年在专科阶段写毕业设计报告时,光是“怎么开头”“怎么把一段…

2026/10/13 17:10:09 阅读更多 →
Docker部署Ceph实现RBD镜像创建与挂载全流程

Docker部署Ceph实现RBD镜像创建与挂载全流程

1. 为什么非得用 Docker 部署 Ceph?——从“三台物理机起步”到“单机快速验证”的真实动因很多人看到“Docker 部署 Ceph”第一反应是皱眉:“Ceph 不是分布式存储系统吗?跑在容器里靠谱?”这问题我当年在某高校实验室带学生做存储…

2026/10/13 17:10:09 阅读更多 →
Python机器学习入侵检测系统实战:从NSL-KDD到Flask部署

Python机器学习入侵检测系统实战:从NSL-KDD到Flask部署

简介:这是一份基于Python机器学习的入侵检测系统项目源码,面向希望入门或进阶网络安全与机器学习方向的学习者,可作为毕业设计、课程设计、大作业或工程实训的参考方案。项目围绕网络流量嗅探与异常检测展开,包含数据预处理、特征…

2026/10/13 17:10:09 阅读更多 →
荷兰耕地遥感语义分割:从数据标注到模型训练全流程实战

荷兰耕地遥感语义分割:从数据标注到模型训练全流程实战

简介:这份荷兰耕地语义分割遥感影像数据集面向遥感图像处理、计算机视觉与农业监测方向的研究者和开发者,用于训练和验证耕地识别与像素级分割模型。资源包共2000个文件,以xml标注文件为主要类型,对应每张遥感影像的像素级类别标签…

2026/10/13 17:09:08 阅读更多 →

日新闻

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

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

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

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