目标
在本教程中,您将学习如何:
- 理解拉普拉斯算子的数学原理及其在边缘检测中的应用。
- 掌握 OpenCV 中 Laplacian 函数的使用方法。
- 了解噪声对二阶导数的影响及预处理方法。
- 通过 C++ 和 Python 代码示例实现图像边缘提取。
理论背景
在上一节中,我们学习了如何使用 Sobel 算子。它基于这样一个事实:在边缘区域,像素强度显示出'跳跃'或强度的高度变化。得到强度的一阶导数后,我们观察到边缘的特征是最大值(峰值)。

如果我们取二阶导数会发生什么?

您可以观察到二阶导数在边缘处会穿过零值(Zero Crossing)。因此,我们也可以使用此标准来尝试检测图像中的边缘。但是,请注意,零不仅会出现在边缘,它们实际上可以出现在其他无意义的位置(例如平坦区域的噪声波动)。这可以通过在需要时应用滤波来解决。
拉普拉斯运算符
从上面的解释中,我们推断出二阶导数可用于检测边缘。由于图像是'2D'的,因此我们需要在两个维度上取导数。在这里,拉普拉斯运算符派上了用场。
拉普拉斯运算符的定义如下:
$$\Delta f = \frac{\partial^{2} f}{\partial x^{2}} + \frac{\partial^{2} f}{\partial y^{2}}$$
拉普拉斯运算符在 OpenCV 中由函数 cv::Laplacian 实现。事实上,由于拉普拉斯使用图像的梯度,它在内部调用 Sobel 算子来执行其计算。
噪声敏感性与预处理
拉普拉斯算子对噪声非常敏感。因为它是二阶微分算子,任何微小的灰度波动都会被放大,导致产生大量的虚假边缘。因此,在使用拉普拉斯算子之前,通常建议先对图像进行高斯模糊(Gaussian Blur)处理,以平滑图像并减少噪声的影响。
OpenCV 实现步骤
本程序的主要流程如下:
- 加载图像。
- 通过应用高斯模糊去除噪点,然后将原始图像转换为灰度。
- 将拉普拉斯运算符应用于灰度图像并存储输出图像。
- 将结果转换回 8 位无符号整数格式以便显示。
- 在窗口中显示结果。
关键参数说明
- src_gray:输入图像,通常为灰度图。
- dst:目标(输出)图像。
- ddepth:目标图像的深度。由于我们的输入是
CV_8U(8 位无符号),而拉普拉斯运算可能产生负值,因此我们定义ddepth = CV_16S以避免溢出。 - kernel_size:要在内部应用的 Sobel 算子的内核大小。在此示例中,我们使用 3。
- scale, delta:缩放因子和偏移量,通常保留为默认值 1 和 0。
代码示例 (C++)
#include <opencv2/opencv.hpp>
cv;
std;
{
Mat src, src_gray, dst, abs_dst;
kernel_size = ;
scale = ;
delta = ;
ddepth = CV_16S;
* window_name = ;
* imageName = argc >= ? argv[] : ;
src = (imageName, IMREAD_COLOR);
(src.()) {
();
();
;
}
(src, src, (, ), , , BORDER_DEFAULT);
(src, src_gray, COLOR_BGR2GRAY);
Mat abs_dst;
(src_gray, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT);
(dst, abs_dst);
(window_name, abs_dst);
();
;
}



