PiDiNet:用像素差分卷积实现轻量级边缘检测

发布时间:2026/10/5 13:48:13
PiDiNet:用像素差分卷积实现轻量级边缘检测 做边缘检测的人大概率都经历过这样一个阶段先学Sobel、Prewitt这些经典算子觉得简单又直观后来接触深度学习发现HED、RCF这类CNN模型效果确实好但那动辄几十上百兆的参数又让你觉得它离“高效”这两个字很远。PiDiNet这篇2021年的CVPR论文恰好把这两条路线缝到了一起——它用像素差分的方式改造卷积在保持精度的前提下做到约100万参数、实时推理而且不依赖ImageNet预训练。这篇精读笔记我会拆一拆它的核心设计、网络结构和训练细节也会聊聊我在复现和工程化过程中踩到的一些实际问题。1. 为什么说PiDiNet是边缘检测里的“轻量王牌”1.1 从边缘检测的两条技术路线说起传统的边缘检测算法比如Canny、Sobel、Prewitt本质上都是基于图像灰度的局部变化来做判断。它们的共同点是用一个固定的差分核去扫描整张图把相邻像素之间的强度差异放大从而把“边缘”这种高频信息提取出来。这种方法的好处是快、稳定、无需训练问题也很明显对纹理、光照变化和复杂场景的泛化能力有限稍微换个场景就要调阈值。深度学习时代边缘检测被建模成一个像素级的二分类问题。HEDHolistically-Nested Edge Detection首先引入了侧输出监督RCFRicher Convolutional Features进一步把多尺度特征全部用起来DexiNed又做了一个更宽更深的密集连接网络。这类方法的精度确实上去了但代价是网络深度和参数量一起涨推理速度往往不理想。PiDiNet的出发点很直接深度学习虽然强但边缘检测这个任务本身带有很强的结构性先验——边缘就是强度的不连续。既然如此与其让网络从零去学一个“差分算子”不如直接把差分操作作为先验嵌入卷积结构里。这样网络既保留了学习能力又不至于在训练时把大量参数浪费在重新发明Sobel上。1.2 这篇论文解决的核心问题PiDiNetPixel Difference Networks要解决的核心问题有两个。第一精度和效率的平衡。当时主流的边缘检测网络比如RCF参数量通常在十几MB这个量级在CPU上跑一张图要按秒算。PiDiNet用大量差分卷积替换普通卷积显著减少了需要学习的参数量在BSDS500上的精度又能保持第一梯队。第二大规模预训练的依赖。绝大多数CNN边缘检测器都需要在ImageNet上预训练主干网络然后微调。这带来一个问题预训练特征本身是为图像分类设计的并不完全适配边缘检测这种密集预测任务。PiDiNet从随机初始化开始训练就能达到SOTA水平省掉了预训练这一步训练流程和资源需求都大幅下降。这两个问题在工程上非常现实。我做项目时最怕的就是接一个需要几十GB训练数据预训练的模型训练成本高不说复现还不稳定。PiDiNet这种“从零开始、小模型、高精度”的路线天然适合快速验证和落地。2. 从Prewitt算子到可学习卷积PiDiConv的第一性原理2.1 传统像素差分算子到底在算什么在深入PiDiConv之前有必要把传统差分算子的数学本质讲清楚。拿Prewitt算子举例它在水平方向的核长这样-1 0 1 -1 0 1 -1 0 1这个核的工作方式是用右侧三个像素值的和减去左侧三个像素值的和得到一个水平梯度响应。如果你把图像想象成一座山的地形图这个算子就是在检测“地势在水平方向上变化最快的坡度”。Sobel算子只是在Prewitt的基础上给中间行加了2倍权重让中心像素的影响更大一些。这类算子的一个共同特点是它们对相邻像素的差值像素差分非常敏感对图像的绝对亮度不敏感。这也就意味着两个亮度差了一个常量偏移的相同场景在这些算子下的输出几乎是一样的。这种性质在边缘检测中很有价值因为边缘的定义本身就与亮度绝对值无关只与亮度变化有关。传统算子的局限在于核是固定的、非学习的所以无法针对特定数据集去优化而且它们通常只考虑单个尺度对边缘粗细、纹理复杂度的适应能力有限。2.2 PiDiConv的四种形态差分与卷积怎么组合PiDiConv的设计思路简单说就是把普通卷积的感受野内信息分成两种中心像素本身的值以及中心像素与周围像素的差值。前者保留全局亮度信息后者提取局部梯度信息。两种信息各自通过可学习的权重进行线性组合形成一个新的卷积算子。论文中给出了四种不同的基本结构形态这里我用更工程化的语言重新组织一下结构形态核心计算方式适用场景形态一差分后卷积先对3x3邻域做像素差分再用1x1卷积学习权重融合精度优先适合作为主干的基本单元形态二卷积后差分先用1x1卷积降维再做像素差分参数量更少适合通道数较多的层形态三残差融合普通卷积与差分卷积并行输出相加兼顾低频和高频信息感觉上最稳形态四逐通道差分不跨通道融合只在单个通道内做差分计算量最低适合超轻量部署我个人的理解是形态三最接近ResNet里的残差思想普通卷积负责学习整体结构信息差分卷积负责学习边缘高频信息两者互补后能更快地收敛。2.3 为什么“差分卷积”能加速收敛这个问题我盯了很久后来拿代码试了一下才真正理解。普通卷积网络的初始权重是随机初始化的训练初期网络基本上是在“盲人摸象”需要大量样本和迭代次数才能慢慢学出有效的滤波器。而PiDiConv的初始化可以这样设计把差分部分的权重初始化为类似Prewitt或Sobel的模式把非差分部分的权重初始化为单位映射。这样一来网络初始状态就已经是一个“能用的边缘检测器”后续训练只是在做精细化调整而不是从零开始。这个原理就像教一个人素描。普通CNN是给一张白纸和一支笔让他自己摸索怎么画出轮廓PiDiNet是先在纸上有了一层浅浅的铅笔草稿你要做的只是加深、修正和补细节当然更快、更稳。在实际训练中这种先验带来的收敛速度优势非常明显。论文和我的复现都观察到PiDiNet从随机初始化开始训练通常在几十个epoch内就能达到超过HED的效果而不需要像其他模型那样先跑几十轮预训练热身。3. 网络架构拆解SSD侧监督与CFA聚合3.1 主干网设计VGG16的血统但不需要预训练PiDiNet的主干网络借鉴了VGG16的堆叠方式连续的3x3卷积加ReLU阶段之间用池化降分辨率。但它做了一些很重要的改动。首先所有常规3x3卷积被替换成了PiDiConv这意味着网络的每一层都在显式地做像素差分。其次通道数做了一定压缩整体参数量和计算量远低于标准的VGG16。具体来说一个典型的PiDiNet主干大概包含五个阶段每个阶段的通道数从64往上到256分辨率逐级下降到原图的1/16左右。这样的设计有一个潜台词单靠PiDiConv的先验网络不需要很宽很深就能提取出足够的边缘特征。我在实际测试中也发现即使把通道数再砍一半结构边缘检测的效果下降幅度也比预期小很多这说明差分卷积确实把“有效信息密度”提升了。3.2 侧输出深度监督HED/RCF一脉相承的训练技巧如果只是把用PiDiConv堆一个VGG-like的骨架训练仍然不容易收敛尤其是只用最终层输出时梯度在深层往回传会逐渐消失。PiDiNet沿用了HED提出的侧输出监督Side-output Supervision策略。具体做法是每次池化之后的分支分别接一个边缘检测头产生该尺度的边缘图。训练时每一个侧输出都会与ground truth计算损失最终的总损失是各侧输出损失的加权和。这样做的好处是浅层也能直接受到边缘标签的监督梯度不会因为网络深而弥散。从实现角度侧输出头通常包括一个1x1卷积把特征图降维到单通道和一个上采样层把分辨率恢复到原图大小。上采样方式用双线性插值即可不用转置卷积因为转置卷积容易带来棋盘格伪影。3.3 CFA上下文特征聚合多尺度信息不靠堆层多尺度信息在边缘检测里很关键——粗尺度边缘对应物体轮廓细尺度边缘对应纹理细节两者需要融合。PiDiNet没有单独设计复杂的金字塔结构而是用了一个轻量的Contextual Feature Aggregation模块。CFA的想法是把各阶段侧输出头的特征图已经统一分辨率沿通道维度拼接起来然后过一个1x1卷积做加权融合。这种融合方式与RCF类似但PiDiNet的CFA是在不同层级的特征上操作并且在融合之后又接了一个很小的卷积层做平滑。我觉得CFA最大的价值在于它足够简单、参数足够少。在工程部署时1x1卷积几乎不增加推理耗时但能有效把多层感知域的信息互补起来。相比之下如果换成FPN那种逐层上采样再相加的结构参数和延时都会显著上升。4. 实验结果怎么看三个数据集的含金量4.1 BSDS500上精度与速度的平衡BSDS500是边缘检测最常用的基准数据集包含200张训练图、100张验证图、200张测试图。PiDiNet在测试集上的ODS最佳数据集尺度F值大约在0.807左右OIS最佳单图尺度F值大约在0.824。这个成绩放到2021年即使不算全面碾压RCF和HED也已经稳在第一梯队而且它的参数量只有约100万推理速度在普通GPU上能到200fps级别。下面是我整理的几组对比数据来自论文和公开实现模型参数量BSDS500 ODS是否需要ImageNet预训练HED14.7M0.788是RCF14.4M0.811是CED22.0M0.803是PiDiNet1.0M0.807否从表格里能明显看出PiDiNet用不到RCF十分之一的参数量达到了几乎一样的精度。这种“以少胜多”的效果很大程度上正是像素差分先验带来的红利。4.2 NYUDv2与Multicue跨域泛化能力NYUDv2是室内深度图像数据集RGB图像含有大量弱光照和复杂纹理边缘检测难度更高。PiDiNet在NYUDv2上的ODS大约在0.79的水平。这里有个值得注意的是BSDS500训练出来的模型直接往NYUDv2上迁移效果会下降但下降幅度比常规CNN要小。Multicue是另一个包含多种自然图像的数据集边界和纹理边缘被分开标注。PiDiNet在Multicue边界数据集上的表现同样靠前。我的解读是像素差分本质上对光照变化有更强的鲁棒性因为差分运算相当于做了某种意义上的亮度归一化所以跨域泛化能力更稳。4.3 不预训练是个什么概念对工程落地的影响不依赖ImageNet预训练这一点在实际项目中是很有分量的。ImageNet预训练不仅意味着下载几GB的权重文件还意味着训练流程中要考虑预训练任务与目标任务之间的分布差异。对于医疗图像、工业缺陷检测这类与自然图像差异很大的领域ImageNet预训练权重甚至可能起副作用。PiDiNet从随机初始化训练只需要目标领域自己的标注数据就省掉了预训练适配套路。我在自制的工业划痕数据集上试过直接在几百张标注图上训练PiDiNet效果基本能用而RCF要明显更依赖ImageNet初始化。这个差异对有数据隐私要求或场景特殊的项目来说非常关键。5. 复现与工程化实践中的几个关键点5.1 差分卷积落地时的padding与感受野细节复现PiDiNet的第一关是自定义的PiDiConv算子。多数人会在padding这里翻车差分操作需要访问邻域像素如果在图像边界不做特殊处理边界像素会缺少邻居导致差分值异常。我建议的做法是在PiDiConv内部显式做paddingpadding模式用reflect或replicate而不是默认的zero padding。因为zero padding会在边界引入一个“假边缘”训练时网络会学到错误的边界响应推理时输出图的边缘会有明显的边框伪影。这个细节论文没有细讲但实际影响很大。还有一个感受野的细节PiDiConv单层是3x3的差分感受野和普通3x3卷积一致。但因为差分操作本身更“稀疏”只关注中心与周围的差值在堆叠多层之后网络整体的有效感受野往往比同深度的普通CNN更大。这其实也是为什么PiDiNet不堆到几十层也能出效果的原因之一。5.2 数据增强与标签处理BSDS500的融合标注BSDS500的ground truth是多个标注者标注的二值边缘图。很多初学者直接把多个标注结果平均后作为单一标签这会丢失单标注中的细节信息。HED和RCF的做法是对每个标注者的边缘图分别计算损失然后取平均。PiDiNet的官方实现也是沿用了这一策略我复现时同样建议这么做。数据增强方面训练时随机裁剪224x224的patch加上水平翻转、垂直翻转、90度旋转等操作。注意旋转之后边缘的连续性依然保持但方向变了这能提高模型对边缘方向的鲁棒性。Color jitter这类颜色增强不建议太强因为边缘检测应当对颜色本身不敏感过度做颜色扰动反而可能引入噪声。5.3 推理加速与量化部署心得PiDiNet的模型本身就小FP32权重大约不到10MB实际上非常适合做端侧部署。我试过两条落地路径第一条是ONNX导出加TensorRT推理。因为PiDiConv本质上是标准卷积的变体只要把自定义算子替换为等价的标准卷积或分组卷积组合就可以顺利导出ONNX。在TensorRT上做FP16推理速度比PyTorch原版还能再快一倍左右。第二条是直接量化到INT8。因为差分运算本质上是计算差值数值动态范围不大对量化的敏感性比普通卷积低不少。我在一个轻量边缘盒子上测试过INT8量化后精度损失大概在1-2个点对很多结构检测任务来说完全可以接受。还有一个工程上的小提醒输出后处理不能省。边缘检测模型输出的是一个连续的概率图要得到最终的边缘折线需要做阈值化和非极大值抑制edge NMS。很多复现项目只关注模型推理忽略NMS环节导致F-score始终上不去。PiDiNet论文里用的edge NMS逻辑并不复杂但对指标的影响非常显著。在实际操作中我通常先把输出概率图做一个3x3的最大值抑制再根据阈值做二值化最后用细线化算法比如形态学骨架化去掉多余的毛刺。整套后处理加在ONNX外面C实现也就几百行代码。就我个人这几年的使用感受PiDiNet在“精度-速度-训练成本”这个三角里找到了一个很舒服的平衡点。如果你手头有几百张标注图想在一天之内训练出一个能落地的边缘检测模型它几乎是最省事的方案之一。当然它也不是万能的在纹理极端密集或者低对比度场景下它仍然会出现漏检这时候需要结合条件随机场或者后处理修正来兜底。但至少对我来说从RCF迁移到PiDiNet之后模型的体积小了十倍训练时间从小时级降到分钟级部署端的压力也小了很多。如果你也在做类似的边缘检测项目我建议先按论文把结构搭起来跑通BSDS500的复现再换到自己领域的数据上做微调会顺很多。