OpenCV线性滤波实战:均值、高斯、方框滤波原理与选型指南
1. 模糊图像这件事到底在解决什么问题刚接触OpenCV那会儿我对“模糊”这个操作是有点抗拒的。辛辛苦苦拍到的画面、跑出来的数据为什么要主动把它弄糊后来做缺陷检测项目被噪声折腾得没脾气才真正理解模糊不是目的而是手段。它本质上是一种邻域加权运算用周围像素的加权结果去替换中心像素从而把那些突兀的、孤立的噪点“抹平”让后续的边缘检测、阈值分割、轮廓提取能稳定工作。这篇内容围绕OpenCV中的线性滤波展开重点讲清楚三件事均值滤波、高斯滤波、方框滤波这三种最常用的平滑手段它们各自的数学本质是什么、参数怎么调、什么场景该用哪个、以及实际写代码时容易踩哪些坑。适合已经会读写图像、想进一步把预处理做扎实的读者也适合做机器视觉、图像分析、自动化检测方向的朋友当作一份可复现的操作笔记。需要先明确一个概念线性滤波指的是滤波核kernel与图像局部区域做卷积时输出是输入像素的线性组合。与之相对的是中值滤波、双边滤波这类非线性方法。线性滤波的优点是计算快、可分离、理论清晰缺点是会无差别地模糊边缘。理解了这个取舍选型就不会盲目。2. 线性滤波的底层逻辑与方案选型2.1 卷积核一切平滑操作的起点线性滤波的核心是一个小矩阵业内叫卷积核或滤波核。以3×3的均值核为例它长这样1/9 1/9 1/9 1/9 1/9 1/9 1/9 1/9 1/9运算时把这个核盖在图像某个像素及其8邻域上对应位置相乘再求和结果就是该像素的新值。因为核里所有系数相等且总和为1所以输出是邻域的平均值图像自然变“糊”。这里有个关键点很多人忽略核的总和必须为1否则图像整体亮度会漂移。如果总和大于1图像会变亮小于1则变暗。OpenCV的内置函数会自动处理归一化但如果你自己用filter2D手写核就得自己保证这一点。2.2 三种线性滤波的定位差异滤波类型核的特点计算速度边缘保持典型用途方框滤波所有权重相等可选归一化最快差快速降噪、求局部均值均值滤波方框滤波的归一化特例快差一般性平滑高斯滤波权重按距离衰减中等较好保留结构的降噪选型的逻辑其实很朴素如果你只想要一个“糊”的结果且追求速度用均值如果你希望中心像素更重要、边缘过渡更自然用高斯。方框滤波更多是作为理解原理的入口实际项目里直接用均值滤波的场景更多。高斯核之所以权重按距离衰减是因为它模拟了自然界中“近处影响大、远处影响小”的规律。一个标准差为σ的高斯核中心权重最高向外迅速下降。这个特性让它在平滑噪声的同时不会像均值滤波那样把边缘糊成一团。2.3 核大小与σ的取舍核大小决定了参与运算的邻域范围。3×3的核只考虑紧邻的8个像素5×5考虑24个7×7考虑48个。核越大平滑越强但细节丢失也越严重计算量按平方增长。高斯滤波还多一个参数σ标准差。σ越大权重分布越平缓模糊效果越接近均值滤波σ越小中心权重越突出模糊越轻微。OpenCV里如果σ设为0它会根据核大小自动推算公式大致是σ 0.3 × ((ksize - 1) × 0.5 - 1) 0.8这个自动推算在多数场景够用但如果你对模糊程度有精确要求建议手动指定σ并做几次对比实验。注意核大小必须是正奇数。设成偶数会导致核没有唯一的中心像素OpenCV会直接报错。3. 三种滤波的实操细节与参数解析3.1 均值滤波最直白的平滑均值滤波在OpenCV里对应cv2.blur()参数只有两个输入图像和核大小。import cv2 import numpy as np img cv2.imread(test.jpg) # 3x3均值滤波 blur_3 cv2.blur(img, (3, 3)) # 7x7均值滤波 blur_7 cv2.blur(img, (7, 7))它的行为非常直观每个像素变成周围k×k个像素的平均值。3×3核下每个输出像素是9个输入像素的算术平均。实操心得均值滤波对高斯噪声有一定抑制效果但对椒盐噪声几乎无效因为椒盐噪声是极值平均之后只是把极值分摊到周围噪点变成了一片模糊的斑。椒盐噪声应该用中值滤波处理这是另一个话题。还有一个容易踩的坑均值滤波对细线和小点的破坏是毁灭性的。如果你后续要做边缘检测3×3的均值滤波可能就把你要找的细边缘抹掉了。我一般会先用原图跑一遍边缘检测再决定要不要加平滑、加多大。3.2 方框滤波均值滤波的通用形式方框滤波用cv2.boxFilter()比均值滤波多一个normalize参数。# 归一化方框滤波等价于均值滤波 box_norm cv2.boxFilter(img, -1, (3, 3), normalizeTrue) # 非归一化方框滤波核内像素直接求和 box_unnorm cv2.boxFilter(img, -1, (3, 3), normalizeFalse)当normalizeTrue时方框滤波和均值滤波结果完全一致。当normalizeFalse时输出是核内像素的和数值会远大于255对于8位图像会直接截断成白色。这个模式在实际降噪中很少用但在计算局部积分图、求局部亮度和等场景下有价值。第二个参数ddepth设为-1表示输出图像深度与输入一致。如果你做非归一化方框滤波建议把ddepth设为cv2.CV_32F或cv2.CV_64F避免8位溢出。为什么要有方框滤波因为它揭示了均值滤波的本质——就是一个归一化的方框核。理解了这一点你就能自己用filter2D手写均值滤波kernel np.ones((3, 3), np.float32) / 9 manual_blur cv2.filter2D(img, -1, kernel)这段代码的结果和cv2.blur(img, (3, 3))完全一样。手写一遍的好处是你以后可以随意改核里的权重做自定义的线性滤波。3.3 高斯滤波保留结构的平滑高斯滤波是实际项目里用得最多的一种。cv2.GaussianBlur()有三个关键参数核大小、σX、σY。# 5x5高斯核σ自动推算 gauss_auto cv2.GaussianBlur(img, (5, 5), 0) # 5x5高斯核σX1.5σY1.5 gauss_manual cv2.GaussianBlur(img, (5, 5), 1.5, 1.5) # 只指定σXσY默认等于σX gauss_single cv2.GaussianBlur(img, (5, 5), 1.5)高斯核的生成过程是这样的对于核内每个位置(i, j)计算它到中心的距离代入二维高斯函数G(i, j) (1 / (2πσ²)) × exp(-(i² j²) / (2σ²))然后对所有值归一化使总和为1。距离中心越远权重越小这就是它比均值滤波“聪明”的地方。σ和核大小的关系有个经验法则核半径一般取3σ左右。比如σ1核大小取7×7半径3就足够覆盖主要权重σ2核大小取13×13。如果核太小而σ太大高斯核会被截断效果失真如果核太大而σ太小核边缘的权重几乎为0浪费计算。可分离性是高斯滤波的一个重要优化点。二维高斯核可以分解成两个一维高斯核的乘积先水平方向卷积再垂直方向卷积计算量从O(k²)降到O(2k)。OpenCV内部已经做了这个优化所以你不需要手动分离但知道这个原理有助于理解为什么高斯滤波在大核下依然很快。提示如果σX和σY不同会得到椭圆方向的高斯模糊这在处理有方向性的运动模糊时有特殊用途但一般降噪场景保持两者相等即可。4. 完整实操流程与效果对比4.1 环境准备与测试图像我习惯用一张带明显噪声和细节的图来做对比实验。下面这段代码生成一张合成测试图包含平坦区域、边缘、细线和随机噪声方便观察不同滤波的效果差异。import cv2 import numpy as np # 创建512x512的测试图 h, w 512, 512 img np.zeros((h, w), dtypenp.uint8) # 画几个不同灰度的矩形块 img[50:150, 50:150] 80 img[50:150, 200:300] 160 img[200:300, 50:300] 120 # 画细线 cv2.line(img, (350, 50), (350, 450), 200, 1) cv2.line(img, (400, 50), (400, 450), 200, 2) # 加高斯噪声 noise np.random.normal(0, 25, (h, w)).astype(np.int16) noisy np.clip(img.astype(np.int16) noise, 0, 255).astype(np.uint8) cv2.imwrite(noisy.png, noisy)这张图的好处是平坦区域能看出噪声抑制效果边缘能看出模糊程度细线能看出细节保留能力。4.2 三种滤波的对比实验# 均值滤波 mean_3 cv2.blur(noisy, (3, 3)) mean_5 cv2.blur(noisy, (5, 5)) # 高斯滤波 gauss_3 cv2.GaussianBlur(noisy, (3, 3), 0) gauss_5 cv2.GaussianBlur(noisy, (5, 5), 0) # 方框滤波归一化 box_3 cv2.boxFilter(noisy, -1, (3, 3), normalizeTrue) # 计算PSNR做定量对比 def psnr(original, processed): mse np.mean((original.astype(np.float64) - processed.astype(np.float64)) ** 2) if mse 0: return float(inf) return 10 * np.log10(255 ** 2 / mse) print(f均值3x3 PSNR: {psnr(img, mean_3):.2f} dB) print(f均值5x5 PSNR: {psnr(img, mean_5):.2f} dB) print(f高斯3x3 PSNR: {psnr(img, gauss_3):.2f} dB) print(f高斯5x5 PSNR: {psnr(img, gauss_5):.2f} dB) print(f方框3x3 PSNR: {psnr(img, box_3):.2f} dB)我实测下来在这张合成图上3×3高斯滤波的PSNR通常比3×3均值滤波高1到2个dB5×5的差距更明显。原因就是高斯核给中心像素更高权重对边缘的破坏更小。4.3 参数选择的实操记录核大小怎么定我的经验是从3×3开始试如果噪声还明显就升到5×5再不行就7×7。但要注意核大小超过7×7之后计算量上升很快而且模糊效果已经很强很多细节会丢失。σ怎么定如果核大小是kσ的合理范围大致是0.3×((k-1)×0.5 - 1) 0.8到0.5×k之间。比如k5σ在1.1到2.5之间比较合理。σ太小等于没模糊σ太大就退化成均值滤波。下面这个表格是我在实际项目中总结的选型参考场景推荐方法核大小σ理由一般高斯噪声高斯滤波3×3或5×5自动平衡速度与效果强噪声快速处理均值滤波5×5无速度优先边缘检测前预处理高斯滤波3×30.8~1.2轻微平滑保留边缘大区域均值计算方框滤波按需无可非归一化求积分实时视频流高斯滤波3×3自动可分离速度快4.4 边界处理容易被忽略的细节滤波时图像边缘的像素没有完整的邻域OpenCV默认用反射边界BORDER_REFLECT_101来填充。这个默认值在多数场景没问题但如果你做的是精确的数值计算边界处理方式会影响结果。cv2.blur和cv2.GaussianBlur没有暴露边界参数但cv2.filter2D和cv2.boxFilter可以指定# 指定边界填充方式 result cv2.boxFilter(noisy, -1, (3, 3), normalizeTrue, borderTypecv2.BORDER_REPLICATE)常用的边界类型有BORDER_REFLECT_101以边缘为轴反射不重复边缘像素OpenCV默认BORDER_REPLICATE直接复制边缘像素BORDER_CONSTANT用常数填充需要额外指定值BORDER_WRAP环绕填充适合周期性图像注意边界处理对图像中心区域没有影响只影响边缘几个像素。如果你的后续处理只关注中心区域可以忽略这个细节但如果做全图统计边界差异会带来微小偏差。5. 常见问题与排查技巧实录5.1 滤波后图像变亮或变暗这是最典型的问题几乎每个手写卷积核的人都遇到过。原因就是核的总和不为1。比如你写了一个3×3的核所有元素都是1总和是9输出就是原图的9倍8位图像直接截断成白色。解决方法很简单把核里每个元素除以总和。kernel np.ones((3, 3), np.float32) kernel kernel / kernel.sum() # 归一化用OpenCV内置的blur、GaussianBlur、boxFilter(normalizeTrue)不会出现这个问题因为它们内部已经做了归一化。5.2 核大小设成偶数报错OpenCV的滤波函数要求核大小必须是正奇数。设成(4, 4)会抛出类似这样的错误error: (-215:Assertion failed) ksize.width 0 ksize.width % 2 1 ...原因前面说过偶数核没有唯一的中心像素。解决办法就是改成最近的奇数比如4改成5或3。5.3 高斯滤波σ设0会怎样σ设0时OpenCV会根据核大小自动计算σ。这个自动值在多数场景是合理的但如果你发现模糊程度不符合预期可以手动指定σ做对比。我一般会跑三组σ0自动、σ1.0、σ2.0看哪组在噪声抑制和细节保留之间平衡最好。5.4 滤波后边缘检测效果反而变差这说明平滑过度了。均值滤波和高斯滤波都会模糊边缘如果核太大Canny之类的边缘检测器就找不到足够的梯度。解决办法是减小核大小或者改用双边滤波这种保边滤波。排查思路是这样的先用原图跑边缘检测记录边缘数量和位置加3×3高斯滤波再跑边缘检测对比差异如果边缘明显减少说明平滑太强降到更小的核或更小的σ如果噪声导致边缘检测出现大量伪边缘说明平滑不够适当加大核5.5 彩色图像怎么处理cv2.blur和cv2.GaussianBlur可以直接处理三通道彩色图像它们会对每个通道独立滤波。但要注意如果三个通道的噪声特性不同独立滤波可能导致颜色偏移。更稳妥的做法是转到HSV或Lab空间只对亮度通道滤波再转回RGB。# 转Lab空间只对L通道滤波 lab cv2.cvtColor(img, cv2.COLOR_BGR2Lab) l, a, b cv2.split(lab) l_blur cv2.GaussianBlur(l, (5, 5), 0) lab_blur cv2.merge([l_blur, a, b]) result cv2.cvtColor(lab_blur, cv2.COLOR_Lab2BGR)这样做的好处是颜色信息不受影响只有亮度被平滑视觉上更自然。5.6 性能优化大核下的速度问题高斯滤波虽然可分离但核很大时仍然慢。如果做实时视频处理3×3或5×5的核基本够用再大就要考虑降采样后再滤波或者用积分图做方框滤波。方框滤波有个天然优势可以用积分图在O(1)时间内计算任意大小的局部均值与核大小无关。OpenCV没有直接暴露这个接口但你可以自己用cv2.integral实现。# 用积分图实现快速方框滤波 integral cv2.integral(noisy, cv2.CV_64F) # 后续通过积分图查表计算任意矩形区域的均值这个技巧在需要大核均值滤波时非常有用速度提升是数量级的。5.7 常见问题速查表问题现象可能原因解决方法图像整体变亮/变暗核未归一化核除以总和报错ksize相关核大小为偶数改为奇数边缘检测失效平滑过度减小核或σ彩色图像颜色偏移各通道独立滤波转Lab只滤L通道大核速度慢计算量大用积分图或降采样椒盐噪声滤不掉线性滤波不适合改用中值滤波边界出现异常边界填充方式指定borderType提示线性滤波对椒盐噪声基本无效这是它的原理决定的。椒盐噪声是极值平均之后只是把极值扩散不会消除。遇到椒盐噪声直接上cv2.medianBlur不要在线性滤波上浪费时间。6. 从线性滤波延伸出去的几个方向把均值、高斯、方框这三种线性滤波吃透之后你会发现很多图像处理操作都是它们的变体或组合。比如图像金字塔的构建底层就是对图像做高斯滤波再降采样SIFT特征的尺度空间也是一系列不同σ的高斯模糊。理解了高斯核的生成和可分离性再看这些算法就不会觉得神秘。另一个方向是自定义线性滤波核。用cv2.filter2D你可以实现锐化、浮雕、边缘增强等效果本质上都是设计不同的卷积核。比如锐化核# 锐化核 sharpen np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], dtypenp.float32) sharpened cv2.filter2D(img, -1, sharpen)这个核的总和是1中心权重5周围-1效果是增强中心像素与周围的差异视觉上更清晰。但要注意锐化会放大噪声所以通常先做轻微高斯平滑再锐化。我在实际项目里的体会是预处理阶段不要追求一步到位。先做轻微平滑跑一遍后续算法看效果再决定要不要加强。很多时候3×3高斯滤波就够了上5×5反而把有用信号也滤掉了。滤波参数没有万能值都是针对具体图像和具体任务调出来的。

相关新闻

COCO人体关键点数据集准备避坑指南

COCO人体关键点数据集准备避坑指南

1. 为什么“准备COCO Keypoints数据集”不是复制粘贴就能搞定的事很多人第一次接触人体姿态估计任务时,看到教程里轻描淡写一句“下载COCO数据集,用官方脚本转成Keypoints格式”,就以为万事大吉。我去年带一个跨专业转AI的团队做实时动作识别…

2026/10/17 18:57:01 阅读更多 →
双树复小波源码实用指南:从验证到去噪避坑

双树复小波源码实用指南:从验证到去噪避坑

简介:面向图像处理研究者的双树复小波变换完整源代码包,解决了传统小波方向选择性有限的痛点,具备六个方向分辨能力,同时冗余度更小,可广泛用于图像去噪、融合、边缘检测等方向的算法验证与教学演示。资源共五十六个文…

2026/10/17 18:56:59 阅读更多 →
CenterNet数据采样核心解析:从热力图生成到小目标检测优化

CenterNet数据采样核心解析:从热力图生成到小目标检测优化

1. 项目概述:从“点”出发理解目标检测的本质变革CenterNet这个名字,第一次看到时我下意识以为是某种中心化部署架构,直到翻开论文才意识到——它把目标检测这件事,彻底“做薄”了。不是框、不是锚、不是多阶段回归,而…

2026/10/17 19:08:38 阅读更多 →

最新新闻

2026年AI编程工具全解析:33款主流助手与IDE选型指南

2026年AI编程工具全解析:33款主流助手与IDE选型指南

2024年大家还在争论“AI能不能写代码”,到2026年这个问题基本不需要讨论了。我今年在好几个项目里把AI编程工具从“偶尔试用”变成了“日常主力”,从代码补全到自动化测试再到完整功能模块的实现,工具链已经成熟得超出预期。但问题也变成了另…

2026/10/17 21:02:08 阅读更多 →
Vibe Coding第二课:零基础搭建个人主页和数字分身

Vibe Coding第二课:零基础搭建个人主页和数字分身

Vibe Coding这个词,最近在开发者圈子里被反复讨论,但对真正零基础的人来说,它最诱人的点其实特别简单:你不需要先把编程学个半吊子,就能做出能给别人看的东西。第二课我们直接来干一件特别实在的事——从0到1搭一个你自…

2026/10/17 21:02:08 阅读更多 →
分步傅里叶法解NLS方程:MATLAB仿真孤子传输实战

分步傅里叶法解NLS方程:MATLAB仿真孤子传输实战

简介:非线性光纤光学与光通信领域的学习者、研究人员,常需掌握分步傅里叶法求解非线性薛定谔方程(NLS)的数值实现。该资源包提供了一份MATLAB源代码及详细解析文档,内容涵盖NLS方程建模、分步傅里叶法原理、代码结构梳…

2026/10/17 21:02:08 阅读更多 →
MATLAB调用外部软件:控件化封装与COM/system/MEX选型实战

MATLAB调用外部软件:控件化封装与COM/system/MEX选型实战

1. 项目缘起与整体设计思路1.1 为什么要在MATLAB里“调用”外部软件做过工程仿真或者数据处理的朋友大概率遇到过这种场景:手头有一套用MATLAB写的算法主流程,但某个关键环节依赖一个独立的第三方软件——可能是某个专业的求解器、一个老旧的C计算程序、…

2026/10/17 21:02:08 阅读更多 →
全网最全Python课程PDF如何高效利用:拆目录、验代码、避坑指南

全网最全Python课程PDF如何高效利用:拆目录、验代码、避坑指南

简介:一份以 PDF 文档形式整理的全网 Python 系统课程学习路线,适合零基础入门到希望进阶的开发者使用。文档提炼了 637 集课程的整体框架,按 Python 基础、进阶、终极、爬虫四篇展开,覆盖 Python 基础语法、坦克大战实战、网络并…

2026/10/17 21:02:08 阅读更多 →
约瑟夫环C语言循环链表实现:从建环到出圈的完整方案

约瑟夫环C语言循环链表实现:从建环到出圈的完整方案

简介:这是一份面向C语言初学者与数据结构学习者的约瑟夫死亡游戏完整实现资料,围绕循环链表这一核心结构展开,帮助读者理解环形链表的创建、遍历与结点删除等经典操作。资源包内仅含1个docx文档,大小约18KB,以文字形式…

2026/10/17 21:01:07 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →