文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

目标

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

  • 使用OpenCV函数 Laplacian 实现拉普拉斯算子的离散模拟。

理论

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

    Previous theory
  2. 如果我们采用二阶导数,会发生什么?

    Second derivative

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

第 1 段(可获 2 积分)

拉普拉斯算子

  1. 从上面的解释,我们推导出二阶导数可以用于检测边缘。 由于图像是“2D”,我们需要在两个维度上取导数。 这里,使用拉普拉斯算子会很方便。
  2. 拉普拉斯算子的定义是:

Laplace(f) = \dfrac{\partial^{2} f}{\partial x^{2}} + \dfrac{\partial^{2} f}{\partial y^{2}}

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

代码

  1. 这个程序是做什么的?
    • 加载图像
    • 通过应用高斯模糊来去除噪声,然后将原始图像转换为灰度图
    • 将拉普拉斯算子应用于灰度图像并存储输出图像
    • 在窗口中显示结果
  2. 教程代码如下所示。 您也可以从这里下载
第 2 段(可获 2 积分)
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>

using namespace cv;

/** @function main */
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;
  char* window_name = "Laplace Demo";

  int c;

  /// Load an image
  src = imread( argv[1] );

  if( !src.data )
    { return -1; }

  /// Remove noise by blurring with a Gaussian filter
  GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );

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

  /// Create window
  namedWindow( window_name, CV_WINDOW_AUTOSIZE );

  /// Apply Laplace function
  Mat abs_dst;

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

  /// Show what you got
  imshow( window_name, abs_dst );

  waitKey(0);

  return 0;
  }
第 3 段(可获 2 积分)

解释

  1. 创建一些必须的变量:

    Mat src, src_gray, dst;
    int kernel_size = 3;
    int scale = 1;
    int delta = 0;
    int ddepth = CV_16S;
    char* window_name = "Laplace Demo";
    
  2. 加载源图:

    src = imread( argv[1] );
    
    if( !src.data )
      { return -1; }
    
  3. 使用高斯模糊算法降噪:

    GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
    
  4. 转成灰度图像,使用函数 cvtColor

    cvtColor( src, src_gray, CV_BGR2GRAY );
    
  5. 对灰度图使用拉普拉斯算法:

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

    参数说明:

    • src_gray: 源图.
    • dst: 目标图
    • ddepth: 目标图色彩深度。这里我们的输入时 CV_8U 我们定义了 ddepth = CV_16S 以避免溢出
    • kernel_size: Sobel 算法的核心大小,本例中取值为 3.
    • scale, deltaBORDER_DEFAULT: 保留默认值即可.
  6. 使用拉普拉斯算法将输出转成一个 CV_8U 图像:

    convertScaleAbs( dst, abs_dst );
    
  7. 在窗口中显示结果:

    imshow( window_name, abs_dst );
    
第 4 段(可获 2 积分)

结果

  1. 在编译上面的代码后,给出一个图像的路径作为参数,我们就可以运行它。 例如,使用下图作为输入:

    Original test image
  2. 我们得到以下结果。 注意树的形状和牛的轮廓是否准确定义(除了在强度非常相似的区域,即在牛头附近)。 此外,请注意,树后面房子的屋顶(右侧)是较差的标记。 这是由于在该区域中对比度较高。

    Original test image
第 5 段(可获 2 积分)

文章评论