形态学梯度是图像形态学处理中的一种基本操作,定义为:
形态学梯度 = 膨胀(dilate) - 腐蚀(erode)
它的主要作用是突出图像中物体的边缘(即灰度变化剧烈的区域)。膨胀会扩大高亮区域,腐蚀会缩小高亮区域,两者相减后得到的就是物体边界附近的“梯度”信息。
OpenCV 提供了 cv2.morphologyEx() 函数,使用 cv2.MORPH_GRADIENT 标志即可计算形态学梯度。
import cv2
import numpy as np
# 读取图像(最好用灰度图)
img = cv2.imread('input.jpg', cv2.IMREAD_GRAYSCALE)
# 定义结构元素(核),常用矩形、椭圆、十字形
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 计算形态学梯度
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
# 显示结果
cv2.imshow('Original', img)
cv2.imshow('Morphological Gradient', gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel:结构元素大小和形状。核越大,提取的边缘越粗。
cv2.MORPH_RECT:矩形核
cv2.MORPH_ELLIPSE:椭圆核
cv2.MORPH_CROSS:十字形核
你还可以使用 cv2.dilate() 和 cv2.erode() 手动计算:
dilated = cv2.dilate(img, kernel)
eroded = cv2.erode(img, kernel)
gradient = cv2.subtract(dilated, eroded) # 或 dilated - eroded
| 梯度名称 | 计算公式 | 说明 |
|---|---|---|
| 基本梯度 | 膨胀 − 腐蚀 | 即 OpenCV 的 MORPH_GRADIENT,最常用 |
| 内部梯度 | 原图 − 腐蚀 | 提取物体内部边缘 |
| 外部梯度 | 膨胀 − 原图 | 提取物体外部边缘 |
边缘检测:比普通 Sobel 等算子对噪声不敏感,能获得封闭、连续的边缘。
字符/文字提取:从背景中分离字符的轮廓。
目标分割预处理:强化目标边界,便于后续轮廓查找。
车牌检测:突出车牌字符与底色之间的边界。
原图:一个白色矩形在黑色背景上
形态学梯度结果:矩形的边框轮廓(白色线条)
对于二值图像,形态学梯度能直接得到物体的边界。
对于灰度图像,梯度结果能反映出各区域的灰度变化强度。
若边缘过粗,可以减小核大小(如 (3,3))。
若边缘不连续,可以增大核或先进行闭运算(MORPH_CLOSE)填充空洞。
Q:形态学梯度与 Canny 边缘检测有什么区别?
A:Canny 基于导数,能得到单像素精细边缘;形态学梯度基于集合运算,边缘较粗但更具抗噪性,且不依赖梯度阈值。
Q:结果图像看起来是灰蒙蒙的,怎么调整?
A:形态学梯度结果中,边缘区域的像素值较高(接近白色),平坦区域接近黑色。可以 cv2.normalize() 或使用 cv2.convertScaleAbs() 增强对比度。

全部评论