OpenCV3学习笔记——边缘检测之拉普拉斯变换Laplacian()

拉普拉斯变化——Laplacian()函数

Human potential is an inestimable and abundant mineral resource, waiting for us to dig.
——人的潜能是一座无法估量的丰富的矿藏,只等着我们去挖掘。

上一篇博文中的Sobel算子,它是通过计算图像的一阶导数来判断图像边缘的,原理我们还记得:就是图像的边缘处,它的像素值会有一个跃变,说明函数的变化率最大,那么也就是说图像的一阶导数达到峰值

那么,对图像求二阶导呢?

1.对图像求二阶导数

我们依然可以找到边缘,为什么?因为一阶导数值最大的地方,二阶导数值为0,我们也可以借助这个性质帮助我们找到边缘(当然会有一些不是边缘的点二阶导数值也是0,但是我们可以通过一些方法将它们筛除掉)
OpenCV3学习笔记——边缘检测之拉普拉斯变换Laplacian()_第1张图片
我们先给出求图像二阶导数的公式:(以x方向的二阶导数为例)
fxx = f(x + h) + f(x - h) - 2f(x)

我下面借用了网上的一张图片来和大家分析以下对图像求一阶导和二阶导的区别,以便我们可以更好地了解拉普拉斯函数
OpenCV3学习笔记——边缘检测之拉普拉斯变换Laplacian()_第2张图片
我们可以看到左图中,红色框框里面的像素,在这个位置像素发生了从100到50的跃变,所以我们可以认为这里是图像的一个边缘,求一阶导数得到中间的像素分布,而当我们求二阶导时,发生了一些神奇的事情,在灰度突变的地方有符号相反的2个数值,也即是对图像求二阶导数产生了一个像素宽的双边缘

而用原图像减去求二阶导数之后的数值可以增强图像的对比度

2.Laplacian()函数的使用

我们先来看看Laplacian()函数的原型:

void Laplacian(InputArray src, OutputArray dst, int ddepth, int ksize=1, double scale=1,
               double delta=0, int borderType=BORDER_DEFAULT )
  1. 第一个参数:输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。
  2. 第二个参数:输出图像,需要和原图像有一样的尺寸和通道数
  3. 第三个参数:int类型的ddept,目标图像的深度
  4. 第四个参数:int类型的ksize,用于计算二阶导数的滤波器的孔径尺寸,大小必须为正奇数,且有默认值1。
  5. 第五个参数:double类型的scale,计算拉普拉斯值的时候可选的比例因子,有默认值1
  6. 第六个参数:double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0
  7. 第七个参数: int类型的borderType,边界模式,默认值为BORDER_DEFAULT

2.1 Laplacian()函数的使用

#include<opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;

int main()
{
    Mat scrimage, dstimage, gray_scrimage, gray_scrimage1, abs_dst, dstimage1;
    scrimage = imread("shuiping.jpg", 1);
    imshow("【原始图】", scrimage);

    cvtColor(scrimage, gray_scrimage, COLOR_RGB2GRAY);
    GaussianBlur(gray_scrimage, gray_scrimage1, Size(3, 3), 0, 0);   //二阶导数对噪声非常敏感,所以去噪这一步非常重要
    Laplacian(gray_scrimage1, dstimage, CV_16S, 3, 1, 0);
    convertScaleAbs(dstimage, abs_dst);   //计算绝对值,并将结果转化为8位

    imshow("【最终效果图】", abs_dst);
}

我们来看看效果:
OpenCV3学习笔记——边缘检测之拉普拉斯变换Laplacian()_第3张图片

OpenCV3学习笔记——边缘检测之拉普拉斯变换Laplacian()_第4张图片
大家有没有注意到,对这个图像求二阶导之后,确实产生了双边缘

你可能感兴趣的:(Learning,OpenCV3)