【opencv 450 Image Processing】Laplace Operator拉普拉斯算子

本文介绍如何使用OpenCV中的Laplacian函数实现拉普拉斯算子,进行图像边缘检测。通过理论讲解与代码示例相结合的方式,展示了拉普拉斯算子的工作原理及其在实际图像处理任务中的应用。

Goal

在本教程中,您将学习如何:

使用 OpenCV 函数 Laplacian() 来实现 Laplacian 算子的discrete analog离散模拟。

Theory

1. 在之前的教程中,我们学习了如何使用 Sobel 算子。 这是基于这样一个事实,即在边缘区域,像素强度显示出“跳跃jump”或强度的高变化。 得到强度的一阶导数,我们观察到边缘的特征是最大值,如图所示:

2. 而且......如果我们取二阶导数会发生什么?

您可以观察到二阶导数为零! 因此,我们也可以使用这个标准来尝试检测图像中的边缘。 但是,请注意,不仅会出现在边缘(它们实际上可以出现在其他无意义的位置); 这可以通过在需要的地方应用过滤来解决

Laplacian Operator

1. 从上面的解释,我们推断二阶导数可以用来检测边缘。 由于图像是“*2D*”,我们需要在两个维度上求导。 在这里,拉普拉斯算子就派上用场了。

2. 拉普拉斯算子定义为:

3. 拉普拉斯算子在 OpenCV 中由函数 Laplacian() 实现。 事实上,由于 Laplacian 使用图像的梯度,它在内部调用 Sobel 算子来执行其计算。

Code

这个程序都做了什么?

加载图像

通过应用高斯模糊去除噪声,然后将原始图像转换为灰度

拉普拉斯算子应用于灰度图像并存储输出图像

在窗口中显示结果

教程代码如下所示。 你也可以从这里raw.githubusercontent.com 下载

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
int main( int argc, char** argv )
{
    // Declare the variables we are going to use
    Mat src, src_gray, dst;
    int kernel_size = 3;
    int scale = 1;
    int delta = 0;
    int ddepth = CV_16S;
    const char* window_name = "Laplace Demo";
    const char* imageName = argc >=2 ? argv[1] : "lena.jpg";
    src = imread( samples::findFile( imageName ), IMREAD_COLOR ); // Load an image
    // Check if image is loaded fine
    if(src.empty()){
        printf(" Error opening image\n");
        printf(" Program Arguments: [image_name -- default lena.jpg] \n");
        return -1;
    }
    // Reduce noise by blurring with a Gaussian filter ( kernel size = 3 )
    GaussianBlur( src, src, Size(3, 3), 0, 0, BORDER_DEFAULT );
    cvtColor( src, src_gray, COLOR_BGR2GRAY ); // Convert the image to grayscale
    Mat abs_dst;
    Laplacian( src_gray, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT );
    // converting back to CV_8U
    convertScaleAbs( dst, abs_dst );
    imshow( window_name, abs_dst );
    waitKey(0);
    return 0;
}

Explanation

Declare variables

//声明我们要使用的变量
Mat src, src_gray, dst;
int kernel_size = 3;
int scale = 1;
int delta = 0;
int ddepth = CV_16S;
const char* window_name = "Laplace Demo";

Load source image

    const char* imageName = argc >=2 ? argv[1] : "lena.jpg";
    src = imread( samples::findFile( imageName ), IMREAD_COLOR ); // Load an image
    //检查图像是否加载正常
    if(src.empty()){
        printf(" Error opening image\n");
        printf(" Program Arguments: [image_name -- default lena.jpg] \n");
        return -1;
    }

Reduce noise

// 通过使用高斯滤波器进行模糊来降低噪声(内核大小 = 3)
GaussianBlur( src, src, Size(3, 3), 0, 0, BORDER_DEFAULT );

Grayscale

cvtColor( src, src_gray, COLOR_BGR2GRAY ); // Convert the image to grayscale

Laplacian operator

Laplacian( src_gray, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT );

参数是:

src_gray:输入图像。

dst:目标(输出)图像

ddepth目标图像的深度。 由于我们的输入是 CV_8U,我们定义 ddepth = CV_16S 以避免溢出

kernel_size:要在内部应用的 Sobel 算子的内核大小。 我们在这个例子中使用 3。

scaledeltaBORDER_DEFAULT:我们将它们保留为默认值。

scale 计算的拉普拉斯值的可选比例因子。 默认情况下,不应用缩放。 有关详细信息,请参阅 getDerivKernels。

delta 在将结果存储到 dst 之前 加到结果的可选 delta 值。Optional delta value that is added to the results prior to storing them in dst .

borderType 像素外推方法,参见 BorderTypes。 不支持 BORDER_WRAP。

Convert output to a CV_8U image

// converting back to CV_8U
convertScaleAbs( dst, abs_dst );

Display the result

imshow( window_name, abs_dst );
waitKey(0);

Results

1. 编译上面的代码后,我们可以运行它,将图像的路径作为参数。 例如,用作输入:

2. 我们得到以下结果。 注意树木和牛的轮廓是如何大致清晰地定义的(除了强度非常相似的区域,即牛头周围)。 另外,请注意,树木后面的房屋屋顶(右侧)是臭名昭著notoriously 的标记。 这是因为该区域的对比度contrast 更高。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值