天天看点

opencv 边缘检测_【3】OpenCV图像处理模块(14)拉普拉斯边缘检测

opencv 边缘检测_【3】OpenCV图像处理模块(14)拉普拉斯边缘检测

Laplacian()函数实现边缘检测。

理论

前面的例子学习了使用Sobel边缘检测。原理是利用边缘区域像素值的跳变。通过求一阶导数,可以使边缘值最大化。如下图所示。

opencv 边缘检测_【3】OpenCV图像处理模块(14)拉普拉斯边缘检测

那么,如果求二阶导数会得到什么呢?

opencv 边缘检测_【3】OpenCV图像处理模块(14)拉普拉斯边缘检测

可以观察到二阶导数为0的地方。因此,可以利用该方法获取图像中的边缘。然而,需要注意的是二级导数为0的不只出现在边缘地方,还可能是一些无意义的位置,根据需要通过滤波处理该情况。

拉普拉斯算子

从上面的解释,可以看出二级导数可以拥有边缘检测。由于图像是二维的,因此需要分别获取两个方向的导数。这里使用的是拉普拉斯算子来进行近似。

拉普拉斯算子用下面公式定义:

opencv 边缘检测_【3】OpenCV图像处理模块(14)拉普拉斯边缘检测

在OpenCV中用Laplacian()函数实现。事实上,函数内部也调用了Sobel算子。

代码

// @tutorials imgproc module 14
// @文件 Laplace_Demo.cpp
// @主题 Laplace算子用于边缘检测
// @修改 CVer
// @日期 2020年1月8日

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"

using namespace cv;

int main( int argc, char** argv )
{
    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 = "lena.jpg";
    src = imread( samples::findFile( imageName ), IMREAD_COLOR ); 
    if(src.empty())
    {
        printf(" Error opening imagen");
        return -1;
    }

    // 高斯滤波( kernel size = 3 )
    GaussianBlur( src, src, Size(3, 3), 0, 0, BORDER_DEFAULT );
    //转为灰度图像
    cvtColor( src, src_gray, COLOR_BGR2GRAY ); 

    // Laplace变换,结果是CV_16S
    Mat abs_dst;
    Laplacian( src_gray, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT );

    // CV_16S转换为CV_8U
    convertScaleAbs( dst, abs_dst );
    // 显示
    imshow( window_name, abs_dst );
    waitKey(0);

    return 0;
}
           

结果

下面是OpenCV示例中给出的结果。可以看出牛和树的轮廓很明显。树后面远处的屋顶,由于对比度很强,所以变换结果很明显。

opencv 边缘检测_【3】OpenCV图像处理模块(14)拉普拉斯边缘检测
opencv 边缘检测_【3】OpenCV图像处理模块(14)拉普拉斯边缘检测