一座城市被拍成航拍照片,制图师的任务是画出一张边界清晰的地图。他没有用尺子慢慢量,而是眯起眼睛找“变化”:公园的浓绿与河道的灰蓝之间、老城区的土黄与新区的米白之间,颜色总是在某个位置突然改变。这改变之处,就是边界。计算机做边缘检测,做的正是同一件事——它把照片拆成一个个像素点,专找亮度突变的位置,再用数学把它们连成轮廓线。本文将以制图师画地图的故事为线索,带你认识 Sobel、Prewitt 两种经典算子,搞懂梯度、卷积、阈值这些核心概念,并亲手写出一段边缘检测代码。
边缘检测是计算机视觉的第一块基石。掌握梯度与算子的本质,你就能理解轮廓提取、OCR 预处理、工业缺陷检测等真实工程任务,也为学习 Canny 与深度学习视觉模型铺平道路。
可视化演示
展示LRU页面置换算法处理页面访问序列的过程,物理帧满时淘汰最久未使用的页面,底部显示完整访问序列。
本节配有交互动效(进入视口后自动加载,约 3KB)。
初始状态 青色方块为物理帧,橙色为最久未使用页 底部序列:绿点命中,红点缺页 淘汰 = argmin(last_access) LRU淘汰最近最久未访问的页面
边缘检测基础
制图师拿到航拍照片,第一件事是找“变”。公园的浓绿、河道的灰蓝、老城区的米白——两种颜色相遇的地方,边界就自动浮出来。你可能以为边界是照片里画好的一条线,其实不是。对计算机来说,照片只是一大堆数字:每个像素一个亮度值,从 0(纯黑)排到 255(纯白)。所谓“边缘”,是制图师在两种区域交界处感受到的那次“突变”。
如果两个相邻像素的亮度几乎一样,说明它们属于同一片区域;如果亮度猛地跳变,说明你正踩在两种区域的交界线上。所以,边缘并不是图像中“预先存在的线”,而是“亮度变化剧烈的位置”这个事实。人眼会自动把这种感觉加工成轮廓线,但计算机需要的是一个可以量化的信号。
按突变方式,边缘大致分三类:阶跃型像河岸,一边是水一边是岸,亮度瞬间跳变;斜坡型像黄昏的光晕,跨过一小段过渡带慢慢变化;屋脊型像地图上的细道路,先升后降形成一条亮线。三者共同点是——亮度在局部区域发生了明显变化。检测边缘的价值在于:它能用极少的线条表达图像最重要的结构,把海量像素压缩成轮廓,就像制图师把整张照片压缩成一张线条地图。
制图师恍然大悟:他要找的从来不是“哪里亮”,而是“哪里变得快”。这个朴素的问题,正是边缘检测算法的出发点——接下来的每一节,都在回答“如何把'变得快'测得更准、画得更漂亮”。
- 像素亮度 $f(x,y)$把图像想象成棋盘,每个格子是一个像素,$f(x,y)$ 记录第 $x$ 列、第 $y$ 行那个格子的亮度。0 表示纯黑,255 表示纯白。
- 相邻差值 $f(x+1,y) - f(x,y)$向右跨一步,看看亮度变了多少。变化为 0 说明还在同一片区域,变化巨大说明正踩在边界上。
- 绝对值 $|\cdot|$变亮和变暗都是变化,制图师只关心“差了多少”,不关心方向,所以取绝对值。
梯度与导数
制图师开车在城里勘查地势:平路上油门轻轻一点就走,遇到陡坡必须狠狠踩下去。“变化率”才是判断边界的关键。在数学里,衡量“变化率”的工具叫导数。导数回答的正是那个问题:当位置挪动一小步,亮度到底上升了多少?
但图像是离散的——像素一格一格排列,没有“无限小”的概念。于是工程师们用一个巧妙的近似:把导数换成相邻像素的差值。想知道水平方向的亮度变化,就看 $f(x+1,y)$ 与 $f(x,y)$ 之差;想知道垂直方向的变化,就比 $f(x,y+1)$ 与 $f(x,y)$。制图师手里那柄“放大镜”,就这样被拆成了两个方向的尺子。
有了水平、垂直两个方向的差值,还能合成两个重要信息:梯度方向——变化最陡的方向,它告诉我们边缘的走向;梯度幅值——变化的总强度,它告诉我们边缘有多明显。可视化演示中的那条灰线是某一行的亮度剖面,蓝线则是沿行方向的梯度:亮度平平的地方梯度接近 0,亮度突变的地方梯度冒出一个尖峰,边缘就在尖峰处。二阶导数也能定位边缘——亮度从加速变亮转为减速的位置,即二阶导数的过零点,正是边缘所在。
有了“变化率”这把尺子,制图师每到一个地方都能报出“这里的明暗变化有多陡”。但只比相邻两个像素,尺子太灵敏——照片上的尘埃、反光都会骗过它。下一节,制图师要给尺子加一层“加权镜片”。
- 偏导数符号 $\frac{\partial f}{\partial x}$二维图像沿 $x$ 方向的变化率,表示“向右走时亮度上升得多快”。
- 离散近似 $f(x+1,y) - f(x,y)$图像没有数学意义上的“无限小”,所以用走一步的差值代替瞬间斜率,简单又够用。
- 两个方向并列水平与垂直两个方向分别求导,合起来才能完整描述一张二维地图上任意方向的边界。
Sobel算子
只比较相邻两点,制图师很快吃了亏:照片上的施工扬尘、水面反光,都会造成局部亮度抖动,被他误认成边界。他需要的是一柄更稳的放大镜——不是只看一步,而是把周围一小片区域的落差综合起来判断。这个想法,就是 Sobel 算子的精髓。
Sobel 算子由两块 3×3 的“模板”(专业术语叫卷积核)组成。水平核 $G_x$ 专门测量水平方向的亮度变化:左边一列乘以 $-1$,右边一列乘以 $+1$,中间一列是 0——如果左右两侧亮度不同,求和结果就会很大,所以它响应的是竖直走向的边界(比如河道两侧的岸线)。垂直核 $G_y$ 把同样的思路转个 90°,专门响应水平走向的边界(比如湖面与天空的交接线)。
使用过程叫卷积:把核盖在图像的一个 3×3 窗口上,对应位置相乘再求和,得到该中心像素的 $G_x$ 与 $G_y$,再用勾股定理合成总强度 $G$。注意看核里的权重:中心行(列)的数字是 $\pm 2$,四周是 $\pm 1$——这是 Sobel 的“加权思想”:离中心越近的像素越可信,话语权越大。就像制图师观察边界时,主要盯着眼前那一小块,余光扫一眼周围。
制图师握着这柄加权放大镜,再看航拍照片,河岸线画得稳稳当当。不过他的同事却持不同意见:“何必厚此薄彼?对每个邻居一视同仁不更公平吗?”——这就是下一节的 Prewitt 算子。
- 核与卷积把 3×3 的核盖在图像的一个 3×3 小窗口上,对应位置相乘再求和,结果就是该中心像素在这个方向上的梯度分量。
- 水平核 $G_x$左边一列乘 $-1$、右边一列乘 $+1$、中间列乘 0,专门测量左右亮度差,响应竖直方向的边界。
- 垂直核 $G_y$转置后的版本,上排乘 $-1$、下排乘 $+1$,测量上下亮度差,响应水平方向的边界。
- 幅值合成 $G = \sqrt{G_x^2 + G_y^2}$把两个方向的梯度当作直角三角形的两条直角边,用勾股定理合成总变化强度。
Prewitt算子
制图师有位性格朴实的同事,他坚持“一碗水端平”:观察边界时,窗内九个邻居同等重要,谁也别想多说话。这个思路就是 Prewitt 算子。它的两块核与 Sobel 长得几乎一样,区别只在权重:Sobel 把中心行(列)的权重从 $\pm 1$ 提到 $\pm 2$,而 Prewitt 老老实实地全部用 $\pm 1$。
Prewitt 的水平核 $P_x$ 三行完全一样(都是 $-1, 0, 1$),垂直核 $P_y$ 三列完全一样。结构极其简单,以至于可以口算:它本质上是“先对上下三行做平均,再求水平差值”——把噪声先平均掉一点,再测变化。这种“平均 + 差分”的组合,让 Prewitt 计算量更小、实现更直观,但代价是对中心像素的信任度降低,抗噪能力略逊于 Sobel。
怎么选?没有绝对优劣,只有是否合适。图像噪声少、追求速度、边缘比较粗壮时,Prewitt 足够用;图像噪声多、需要精细边缘时,Sobel 的加权策略更稳。制图师的做法是:晴朗天气用便宜的 Prewitt 快速出图,风沙天气换 Sobel 细心描线。
无论选哪把尺子,制图师都明白:测出“变化”只是第一步。一张地图要画得干净,还得按工序一步步来——把彩色转成黑白、擦掉灰尘、再决定哪些变化够格画成边界。
- 统一权重核里只有 $1$ 与 $-1$,每个邻居权重相同,体现“一碗水端平”的均值思想。
- 与 Sobel 对比Sobel 中心权重是 $\pm 2$,Prewitt 是 $\pm 1$,对中心像素的关注更少,结构更扁平。
- 代价与收益权重简单带来更快的计算,但平均化处理让它在强噪声下容易漏掉或误报边缘。
检测流程
制图师的工作台上有四道固定工序。第一步,灰度化:把彩色照片转成黑白简稿。颜色有三个通道,亮度只有一个值,先合并成单通道,计算量立刻降为原来的三分之一。第二步,平滑去噪:拿一块“橡皮擦”(专业上叫高斯滤波)把照片上的灰尘颗粒擦掉。噪声在像素层面会产生剧烈的明暗抖动,如果不先擦掉,梯度计算会把它们当成“超强边缘”,像制图师把尘土颗粒当成小岛画进地图。
第三步,计算梯度:用 Sobel 或 Prewitt 对平滑后的图像逐像素求 $G_x$、$G_y$,合成幅值 $G$。这一步得到的是“变化强度图”——每个像素旁边都标注着“这里的亮度变化有多剧烈”。第四步,阈值分割:制图师心里有一条及格线 $T$,高于它的变化才配画成边界,低于它的通通忽略。比较之后,图像变成黑白分明的二值图:白色像素是边缘,黑色像素不是。
四道工序环环相扣,就像制图师的工作台缺一不可。阈值 $T$ 的大小直接影响地图质量:定得太低,地图上全是灰尘留下的假边界;定得太高,细小的河流支脉全被漏掉。怎么定才合适?这就要看下一节的后处理优化了。
阈值分割交付的初稿还很粗糙——边缘往往像毛笔字一样又粗又宽。制图师拿来细笔,准备做最后一道打磨工序。
- 阈值 $T$制图师心里的那条及格线,是“多大变化才算边界”的裁判标准。
- 比较 $G(x,y) > T$逐像素拿梯度幅值与阈值比较,超过及格线的判定为边缘像素,标记为 255(纯白)。
- 输出二值图未达标的置为 0(纯黑),最终得到一幅黑白分明的二值边缘图。
后处理优化
阈值分割之后,边缘是一大片“边缘带”,像毛笔写出的粗笔画,宽达好几个像素。制图师不满意:地图上的边界线应该是一根根纤细的线条。于是他想出一个办法——非极大值抑制:沿着梯度方向(也就是变化最陡的方向)看,只保留那个“最高点”,把旁边的小跟班全部清零。就像山脊上只留下最高的那排石头,边缘带就被收窄成了一条边缘线。
但细线有了,新的问题来了:有些地方线条断了一截。为什么?因为真实世界的边界强弱不一,一处光照暗,梯度幅值就可能跌破阈值。制图师改用双阈值策略:设一道高阈值划“主线”,再设一道低阈值划“候选线”。高于高阈值的像素一定是边缘;低于低阈值的直接丢弃;介于两者之间的,只有与已确认的强边缘相连才被保留。这就像主管先画红杠定主干,助手顺着红杠把细枝末节接续上——连通性分析保证了边缘的连续闭合。
最后再辅以边缘细化(把粗轮廓蚀刻成单像素细线)和连通域筛选(剔除孤立的小噪点),一张干净利落的线条地图就诞生了。这整套后处理,正是 Canny 边缘检测的核心思路:先抑制、再滞后连接,让每条边界既细又完整。
细笔描完,地图上的河岸线、城区线终于干净利落。制图师把这份地图交给城市规划部门——边缘检测的价值,从来不在“画出线”本身,而在这些线能被拿去做什么。
- 梯度方向的邻居 $p_1, p_2$梯度方向是亮度变化最陡的方向,真正的边缘应该比两侧邻居都“突出”,只需比较方向上的前后两个点。
- 比较条件只有同时比两个邻居的梯度幅值都大时,自己才是“最高点”,值得保留。
- 否则置零没当选“最高点”的像素全部清零,粗壮的边缘带就收成了一条细线。
实战应用
地图完工后,边界线被送去支撑各种决策:河道蓝线用于防洪规划,城区界线用于土地丈量。机器视觉世界也是如此——边缘是“形状的语言”,把复杂的像素压缩成结构化的线条,供上层算法使用。几乎所有计算机视觉任务的第一步,都是先问:哪里有边缘?
物体轮廓提取与特征匹配是最直接的应用。把一张图的边缘图与模板图的边缘图对齐,就能判断物体类别和姿态;指纹识别、零件定位、手势识别都依赖这一招。工业质检中,金属表面的划痕与裂纹会在亮度上产生突变,用 Sobel 算出梯度幅值后,缺陷区域会出现异常密集的边缘响应,系统据此快速圈出“嫌疑区”,不必整图送进重型模型。OCR 预处理里,文字区域与空白区域的边缘密度差异巨大:先检测边缘,再统计每个滑窗的边缘密度,就能定位文字块、估算倾斜角度并校正,让后续识别模型事半功倍。
自动驾驶的车道线检测也离不开它:车道线与沥青路面的亮度反差,在梯度图上就是两条清晰的亮线,再配合直线拟合就能还原车道。所以,边缘检测从来不是终点,而是起点——它把一张几百 KB 的照片,提炼成几百条有意义的线段,为更高层的智能决策铺路。从制图师的放大镜到机器的梯度尺,贯穿始终的核心只有一个词:变化。
AI 应用场景
工业零件表面缺陷检测
阶段:图像预处理与特征提取
解决的问题:传统质检靠工人肉眼在产线上找划痕、裂纹,长时间工作容易疲劳漏检;直接上深度学习模型又太“重”,样本少时效果不佳。边缘检测先把灰度图转成边缘图,缺陷区域的边界形成密集的梯度响应,快速圈出“嫌疑区”,再交给后续分类器做精细判断。
具体案例:某汽车零部件厂在传送带上方架设工业相机,对每个金属垫片拍照后用 Sobel 算子计算梯度幅值,再统计环形方向上的边缘密度。正常垫片边缘稀疏均匀,有划痕的垫片在某个方向上出现异常密集的边缘线,系统据此自动剔除不良品,误检率大幅下降。
OCR 文字定位与倾斜校正
阶段:特征提取与区域定位
解决的问题:扫描件里文字区域和空白区域在亮度上差异很大,直接整页识别既慢又贵。边缘检测能快速锚定“文字密布”的区域,缩小识别范围,并利用文字行的边缘走向估算倾斜角。
具体案例:银行票据识别系统中,先对票据做灰度化和高斯平滑,再用梯度幅值图统计每个滑动窗口的边缘密度,边缘密集的窗口聚合成文字块;根据文字块边缘的倾斜角度做旋转校正,再送入 OCR 模型,识别准确率显著提升。
自动驾驶车道线检测
阶段:特征提取与结构化输出
解决的问题:路面与车道线材质不同、亮度反差明显,从整幅图中直接拟合直线很容易被路面纹理干扰。先用边缘检测把车道线转成一组边缘点,后续拟合只需在这些点上工作,稳健又高效。
具体案例:车载摄像头采集路面图像后,先用 Sobel 水平核提取垂直走向的亮度突变(车道线是近似竖直的条带),再经阈值过滤和感兴趣区域筛选,最后用霍夫变换拟合出左右车道线的直线方程,供车辆横向控制模块使用。
Python 演示
def sobel_filter(img): h = len(img) w = len(img[0]) Gx = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]] Gy = [[-1, -2, -1], [0, 0, 0], [1, 2, 1]] edges = [[0] * w for _ in range(h)] for y in range(1, h - 1): for x in range(1, w - 1): gx = 0 gy = 0 for ky in range(3): for kx in range(3): v = img[y + ky - 1][x + kx - 1] gx += Gx[ky][kx] * v gy += Gy[ky][kx] * v mag = (gx * gx + gy * gy) ** 0.5 edges[y][x] = min(int(mag), 255) return edges def make_test_image(size=41, margin=16, dark=30, bright=220): # 生成中央亮方块, 边缘在方块边界处 img = [[dark] * size for _ in range(size)] for y in range(size): for x in range(size): if margin <= x < size - margin and margin <= y < size - margin: img[y][x] = bright return img def threshold_map(edges, t=120): h = len(edges) w = len(edges[0]) return [[255 if edges[y][x] > t else 0 for x in range(w)] for y in range(h)] def main(): img = make_test_image() edges = sobel_filter(img) binary = threshold_map(edges) for row in binary: print("".join("#" if v else "." for v in row)) if __name__ == "__main__": main()
def sobel_filter(img):定义核心函数,输入是二维灰度列表,输出是同尺寸的边缘强度图。gx += Gx[ky][kx] * v把 3×3 核与图像窗口对应相乘再累加,完成一次卷积。mag = (gx * gx + gy * gy) ** 0.5用勾股定理合成横纵两个方向的梯度幅值。edges[y][x] = min(int(mag), 255)把幅值截断到 0-255 的像素范围内。if margin <= x < size - margin and margin <= y < size - margin:创建测试图:中央亮方块、四周暗背景,边界恰好落在方块边缘。return [[255 if edges[y][x] > t else 0 for x in range(w)] for y in range(h)]阈值分割:超过阈值的置 255,否则置 0,得到二值边缘图。print("".join("#" if v else "." for v in row))用#和.把边缘图打印成字符画,一眼看清方块轮廓。
常见误区
误区“边缘检测不就是把图片里本来就有的轮廓线'描'出来吗?我觉得边缘是物体上真实存在的一圈黑线,算法只是把它们找出来。”
正解边缘不是“既有的线”,而是根据亮度突变“计算出来”的位置。想象制图师看航拍照片:公园和河道之间并没有人画一条线,是两种颜色的突变让制图师决定在那里画线。如果两块区域的亮度完全一致,即使物理上属于不同物体,边缘检测也找不到边界;反过来,同一块物体表面的明暗交界(比如光照阴影)也会被检测成边缘。边缘是“计算结果”,不是“扫描结果”。
为何常见:人眼看到轮廓时,大脑已经把“变化”加工成了“线条”,于是误以为线是图像自带的。
误区“Sobel 的水平核 Gx 当然用来找水平边缘,名字里带着'水平'两个字嘛。”
正解名字会骗人。$G_x$ 求的是沿 $x$ 方向(水平方向)的亮度变化率——它响应的是左右两侧亮度不同,也就是竖直走向的边界,像河道两侧的岸线。同理 $G_y$ 求垂直方向的变化,响应的是水平走向的边界,像湖面与天空的交接线。规律是:沿哪个方向求导,检测到的就是垂直于该方向的边缘。
为何常见:把“求导方向”和“边缘走向”搞混了——方向与边缘垂直,这是初学者最容易踩的坑。
误区“阈值越大,留下来的边缘越'真',所以应该尽量把阈值调高,宁缺毋滥。”
正解阈值过高会把弱边缘一起丢掉,真实边界断成一截一截,像制图师只描最粗的河岸、漏掉所有支流。工业上常用的双阈值策略(高阈值定主线、低阈值接续弱边缘)正是为解决这个问题而设计。合适的阈值应该在“保留真实边缘”和“过滤噪声”之间取平衡,而不是一味求严。
为何常见:初学者常以为“严格”等于“准确”,忽略了弱边缘同样携带重要的结构信息。
误区“反正边缘检测只看变化,噪声也是一种变化,应该没什么影响吧?大不了多画几条边缘。”
正解噪声恰恰是边缘检测最大的敌人。随机噪声在像素层面产生剧烈的明暗抖动,梯度计算会把它们当成“超强边缘”——就像制图师把照片上的灰尘颗粒当成了小岛,画出一堆假边界。所以标准流程里必须先做平滑去噪(如高斯滤波),把灰尘擦掉再测变化。千万别跳过这一步。
为何常见:人眼看照片会自动忽略噪点,但算法不会——它一视同仁地计算每一个像素的变化,噪声在数学上和真实边缘没有任何区别。
面试题
Q1. 图像中“边缘”的本质是什么?
- A.图像中颜色偏亮的像素集合
- B.亮度发生剧烈变化的位置← 正确答案
- C.物体预先存在的轮廓线
- D.灰度值最大的连通区域
答案:B。边缘不是图里既有的线,而是“亮度突变”这个事实,B 对。A、D 说的是“亮”,但亮不等于边界;C 把边缘误认为预先存在的线,与“计算得出”矛盾。
Q2. 对离散图像计算梯度,常使用什么替代导数?
- A.相邻像素间的差值← 正确答案
- B.整幅图像的均值
- C.像素灰度的方差
- D.图像色彩的饱和度
答案:A。图像没有“无限小”,工程上用相邻像素的差值近似导数,A 对。均值、方差、饱和度都与“局部变化率”无关,不能替代导数。
Q3. Sobel 水平核 Gx 的中心像素权重是多少?
- A.权重数值为负一
- B.权重数值为零← 正确答案
- C.权重数值为正一
- D.权重数值为正二
答案:B。Sobel 水平核中间列全为 0,中心像素权重自然是 0——它只比较左右两侧,不关心中心本身。负一、正一、正二是其他位置的权重,容易与中心混淆。
Q4. Prewitt 算子与 Sobel 算子最本质的区别是什么?
- A.Prewitt 核更看重中心像素
- B.Prewitt 对邻域像素等权处理← 正确答案
- C.Prewitt 只检测水平方向边缘
- D.Prewitt 不需要合成梯度幅值
答案:B。Prewitt 核全部用 ±1,对每个邻居一视同仁;Sobel 把中心权重提到 ±2,更看重中心。二者都能检测两个方向,也都要合成幅值,所以 C、D 错误。
Q5. 梯度幅值公式 G = sqrt(Gx² + Gy²) 刻画的是什么?
- A.亮度变化的总体强度← 正确答案
- B.边缘在图像中的走向
- C.图像自身的平均亮度
- D.需要设定的阈值大小
答案:A。勾股定理合成的是横纵两个方向变化的总强度,A 对。边缘走向由梯度方向 arctan(Gy/Gx) 决定而非幅值;平均亮度、阈值都与梯度幅值无关。
Q6. 以下哪些属于边缘检测的基本流程步骤?
- A.灰度化去除色彩干扰← 正确答案
- B.平滑滤波降低噪声← 正确答案
- C.计算图像梯度幅值← 正确答案
- D.增强色彩提高饱和度
答案:ABC。标准流程是“灰度化 → 平滑去噪 → 计算梯度 → 阈值分割”,A、B、C 全在其中。D 是图像增强手段,与边缘检测无关,且边缘检测恰恰要丢弃色彩信息。
Q7. 阈值 T 设置过大可能导致什么后果?
- A.弱边缘缺失造成断裂← 正确答案
- B.边缘全部加粗放大
- C.图像分辨率随之提高
- D.噪声边缘数量变多
答案:A。阈值过高会淘汰弱边缘,真实边界断成一截一截,像制图师漏掉所有支流,A 对。阈值大不会加粗边缘、提高分辨率,也不会让噪声边缘变多——恰恰相反,噪声边缘会减少。
Q8. 边缘检测的后处理包括哪些手段?
- A.非极大值抑制细化← 正确答案
- B.双阈值滞后连接← 正确答案
- C.图像灰度化处理
- D.提高图像分辨率
答案:AB。非极大值抑制把粗边缘带收成细线,双阈值用高低两条线连接弱边缘,都是典型后处理,A、B 对。灰度化属于前置流程,提高分辨率与后处理无关。
Q9. 以下哪些因素会影响边缘检测的效果?
- A.图像噪声的强弱水平← 正确答案
- B.梯度阈值的大小← 正确答案
- C.平滑滤波的强度← 正确答案
- D.物体颜色的名称
答案:ABC。噪声会产生假边缘,阈值决定保留多少边缘,平滑强度决定噪声是否被过滤,三者都直接影响结果,A、B、C 对。算法只认亮度数值,不认颜色叫什么名字,D 无关。
Q10. 双阈值策略中,梯度幅值介于低阈值与高阈值之间的像素如何取舍?
- A.与强边缘相连则保留← 正确答案
- B.无条件直接丢弃掉
- C.无条件全部保留
- D.根据色彩深浅决定
答案:A。中间像素是“待定区”:与高阈值确认的强边缘相连就保留(接续断裂的弱边缘),否则丢弃。无条件保留会引入噪声,无条件丢弃会让边缘断裂,色彩深浅与梯度无关。