原始图片:

Sobel 算子结合了高斯平滑和微分,用于计算图像的梯度,从而突出显示边缘。
- import cv2
-
- # 读取图像
- image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
-
- # 使用 Sobel 算子查找水平和垂直边缘
- sobel_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
- sobel_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
-
- # 叠加水平和垂直边缘
- edges = cv2.addWeighted(cv2.convertScaleAbs(sobel_x), 0.5, cv2.convertScaleAbs(sobel_y), 0.5, 0)
-
-
-
- # 显示结果
- cv2.imshow("Original Image", image)
- cv2.imshow("Edges", edges)
-
- cv2.waitKey(0)
- cv2.destroyAllWindows()
函数原型:
sobel = cv2.Sobel(src, ddepth, dx, dy, ksize, scale, delta, borderType)
参数说明:
cv2.CV_64F 表示 64 位浮点数)。cv2.BORDER_DEFAULT)。


Scharr 算子是一种改进的 Sobel 算子,适用于增强边缘检测的精度,在正常的 Sobel 核的尺寸上有更好的性能。
scharr_x = cv2.Scharr(src, ddepth, dx, dy, scale, delta, borderType)
参数说明:
cv2.Sobel() 相同,只是 ksize 参数被硬编码为 3。
- import cv2
- import numpy as np
-
- # 读取图像并转换为灰度图
- image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
-
- # 使用 Scharr 算子计算 x 和 y 方向上的梯度
- grad_x = cv2.Scharr(image, cv2.CV_64F, 1, 0)
- grad_y = cv2.Scharr(image, cv2.CV_64F, 0, 1)
-
- # 将梯度取绝对值并转换为 8 位图像
- abs_grad_x = cv2.convertScaleAbs(grad_x)
- abs_grad_y = cv2.convertScaleAbs(grad_y)
-
- # 合并 x 方向和 y 方向的梯度
- scharr = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
-
- # 显示图像
- cv2.imshow('Scharr Edge Detection', scharr)
- cv2.waitKey(0)
- cv2.destroyAllWindows()

Canny 边缘检测是一种多级边缘检测算法,效果较为显著,常用来检测图像中的明显边缘。
函数原型:
edges = cv2.Canny(image, threshold1, threshold2, apertureSize, L2gradient)
参数说明:
- import cv2
-
- # 读取图像并转换为灰度图
- image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
-
- # 使用 Canny 边缘检测
- edges = cv2.Canny(image, 100, 200)
-
- # 显示图像
- cv2.imshow('Canny Edge Detection', edges)
- cv2.waitKey(0)
- cv2.destroyAllWindows()

Laplacian 算子是一种二阶导数算子,用于检测图像中的边缘。
laplacian = cv2.Laplacian(src, ddepth, ksize, scale, delta, borderType)
参数说明:
cv2.BORDER_DEFAULT。 - import cv2
- import numpy as np
-
- # 读取图像并转换为灰度图
- image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
-
- # 使用 Laplacian 边缘检测
- laplacian = cv2.Laplacian(image, cv2.CV_64F)
-
- # 将结果转换为 8 位图像
- laplacian = cv2.convertScaleAbs(laplacian)
-
- # 显示图像
- cv2.imshow('Laplacian Edge Detection', laplacian)
- cv2.waitKey(0)
- cv2.destroyAllWindows()

Prewitt 算子是另一种一阶导数算子,可以检测水平和垂直边缘。虽然 OpenCV 没有直接提供 cv2.prewitt() 函数,但可以使用 cv2.filter2D 函数自定义 Prewitt 核来实现。
- import cv2
- import numpy as np
-
- # 读取图像并转换为灰度图
- image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
-
- # 定义 Prewitt 核
- prewitt_kernel_x = np.array([[1, 0, -1],
- [1, 0, -1],
- [1, 0, -1]])
- prewitt_kernel_y = np.array([[1, 1, 1],
- [0, 0, 0],
- [-1, -1, -1]])
-
- # 使用 Prewitt 核进行边缘检测
- grad_x = cv2.filter2D(image, cv2.CV_64F, prewitt_kernel_x)
- grad_y = cv2.filter2D(image, cv2.CV_64F, prewitt_kernel_y)
-
- # 计算梯度幅值
- abs_grad_x = cv2.convertScaleAbs(grad_x)
- abs_grad_y = cv2.convertScaleAbs(grad_y)
- prewitt = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
-
- # 显示图像
- cv2.imshow('Prewitt Edge Detection', prewitt)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
罗伯特交叉算子是一种简单且快速的边缘检测算子,适用于检测图像的对角边缘。OpenCV 中没有直接提供罗伯特交叉算子,但可以通过自定义卷积核实现。
- import cv2
- import numpy as np
-
- # 读取图像并转换为灰度图
- image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
-
- # 定义 Roberts 核
- roberts_kernel_x = np.array([[1, 0],
- [0, -1]])
- roberts_kernel_y = np.array([[0, 1],
- [-1, 0]])
-
- # 使用 Roberts 核进行边缘检测
- grad_x = cv2.filter2D(image, cv2.CV_64F, roberts_kernel_x)
- grad_y = cv2.filter2D(image, cv2.CV_64F, roberts_kernel_y)
-
- # 计算梯度幅值
- abs_grad_x = cv2.convertScaleAbs(grad_x)
- abs_grad_y = cv2.convertScaleAbs(grad_y)
- roberts = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
-
- # 显示图像
- cv2.imshow('Roberts Edge Detection', roberts)
- cv2.waitKey(0)
- cv2.destroyAllWindows()

还可以通过自定义卷积核来进行边缘检测。
- import cv2
- import numpy as np
-
- # 读取图像并转换为灰度图
- image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
-
- # 定义自定义卷积核
- custom_kernel = np.array([[-1, -1, -1],
- [-1, 7, -1],
- [-1, -1, -1]])
-
- # 使用自定义卷积核进行边缘检测
- custom_edges = cv2.filter2D(image, cv2.CV_64F, custom_kernel)
-
- # 将结果转换为 8 位图像
- custom_edges = cv2.convertScaleAbs(custom_edges)
-
- # 显示图像
- cv2.imshow('Custom Kernel Edge Detection', custom_edges)
- cv2.waitKey(0)
- cv2.destroyAllWindows()

基于直方图的方法,通过分析图像的灰度直方图来检测边缘。
- import cv2
- import numpy as np
-
- # 读取图像并转换为灰度图
- image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
-
- # 计算图像的直方图
- hist = cv2.calcHist([image], [0], None, [256], [0, 256])
-
- # 找到直方图的峰值
- min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(hist)
-
- # 使用峰值作为阈值进行二值化处理
- _, binary = cv2.threshold(image, max_loc[1] - 30, 255, cv2.THRESH_BINARY)
-
- # 显示图像
- cv2.imshow('Histogram Based Edge Detection', binary)
- cv2.waitKey(0)
- cv2.destroyAllWindows()

adaptiveThreshold()自适应阈值
自适应阈值可以在照明不均匀的情况下检测边缘。
函数原型:
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])
参数说明:
src:输入图像,应为灰度图像(单通道)。maxValue:指定在满足条件时给输出像素赋予的最大值(通常为255)。adaptiveMethod:自适应方法。可选值有:
cv2.ADAPTIVE_THRESH_MEAN_C:基于邻域均值的自适应阈值化方法。cv2.ADAPTIVE_THRESH_GAUSSIAN_C:基于邻域加权均值的自适应阈值化方法。thresholdType:阈值类型,应为 cv2.THRESH_BINARY 或 cv2.THRESH_BINARY_INV。blockSize:指定用于计算阈值的邻域大小,一般为奇数。C:从计算的平均值或加权平均值中减去的常数。
- import cv2
-
- # 读取图像并转换为灰度图
- image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
-
- # 自适应阈值
- adaptive_threshold = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
-
- # 显示图像
- cv2.imshow('Adaptive Threshold Edge Detection', adaptive_threshold)
- cv2.waitKey(0)
- cv2.destroyAllWindows()

threshold()阈值化 (cv2.threshold)
简单的全局阈值化方法,通过固定的阈值来二值化图像以检测边缘。
- import cv2
-
- # 读取图像并转换为灰度图
- image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
-
- # 全局阈值化
- _, threshold = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)
-
- # 显示图像
- cv2.imshow('Global Threshold Edge Detection', threshold)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
