理论:
官方图例:
使用 Sobel 算子进行一阶求导,得到边缘像素是最大值(最高点)。这是基于:在边缘区域中,像素强度显示出“跳跃”或强度的高度变化。获得强度的一阶导数,我们观察到边缘的特征是最大值,如图中所示。
Laplace算子是进行二阶求导,从图上观察到二阶导数为零!因此,我们也可以使用此标准来尝试检测图像中的边缘。但请注意,零不仅会出现在边缘(它们实际上可能出现在其他无意义的位置); 这可以通过在需要时应用过滤来解决。
数学公式:
L
a
p
l
a
c
e
(
f
)
=
δ
2
F
δ
X
2
+
δ
2
F
δ
Y
2
Laplace(f)=\frac{\delta^2F}{\delta X^2}+\frac{\delta^2F}{\delta Y^2}
Laplace(f)=δX2δ2F+δY2δ2F
处理步骤:
- 高斯模糊 - 降噪声, Cv2.GaussianBlur
- 转为灰度图像 ,Cv2.CvtColor
- 拉普拉斯 二阶导数计算 ,Cv2.Laplacian
- 取绝对值 Cv2.ConvertScaleAbs
- 显示结果
API:
Cv2.Laplacian():计算图像的拉普拉斯行列式
参数 | 说明 |
---|---|
InputArray src | 源图像 |
OutputArray dst | 输出图像,将具有与src相同的大小和相同数量的通道 |
MatType ddepth | 目标图像的所需深度 默认填 -1,与源图一致 |
int ksize = 1 | 用于计算二阶导数滤波器的孔径大小,卷积核大小,奇数 |
double scale = 1 | 计算的拉普拉斯值的可选缩放因子(默认情况下不应用缩放) |
double delta = 0 | 可选的增量值,在将结果存储到dst之前添加到结果中 |
BorderTypes borderType = BorderTypes.Reflect101 | 边缘处理方法 |
代码:
/// <summary>
/// Laplacian算子图像边缘处理
/// </summary>
private static void Laplacian(string path)
{
using (Mat src = new Mat(path, ImreadModes.AnyColor | ImreadModes.AnyDepth))
using (Mat dst = new Mat())
{
//步骤
//1:高斯模糊
Mat guss = new Mat();
Cv2.GaussianBlur(src, guss, new Size(3, 3), 0, 0, BorderTypes.Default);
//2:转为灰度图像
Mat gray = new Mat();
Cv2.CvtColor(guss, gray, ColorConversionCodes.RGB2GRAY);
//3:Laplacian算子处理 二阶导数计算
Cv2.Laplacian(gray, dst, -1, 3); //高斯模糊可以变换位图深度
//处理噪声点 二值化 -- 可选
Cv2.Threshold(dst, dst, 0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary);
//4:取绝对值
/*
* 摘要:
* 缩放 ,计算绝对值并将结果转换为bit位
* 参数:
* src: 源数组
* dst: 目标数组
* alpha: 可选比例因子【默认情况下是1】
* beta: 可选增量添加到缩放值中。【默认情况下是0】
*
*/
Cv2.ConvertScaleAbs(dst, dst);
using (new Window("OUTPUT", WindowMode.AutoSize, dst))
using (new Window("GRAY", WindowMode.AutoSize, gray))
using (new Window("GUSS", WindowMode.AutoSize, guss))
using (new Window("SRC", WindowMode.AutoSize, src))
{
Cv2.WaitKey(0);
}
}
}
#endregion
源图与高斯模糊
灰度图与最终拉普拉斯求导图