OpenCV 4.12.0
开源计算机视觉
加载中...
搜索中...
无匹配项
更多形态学变换

上一教程: 腐蚀与膨胀
下一教程: 击中或击不中

原始作者Ana Huamán
兼容性OpenCV >= 3.0

目标

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

  • 使用OpenCV函数 cv::morphologyEx 应用形态学转换,例如
    • 开运算
    • 闭运算
    • 形态学梯度
    • 顶帽
    • 黑帽

理论

注意
以下解释摘自Bradski和Kaehler的著作《Learning OpenCV》。

在上一教程中,我们介绍了两个基本的形态学操作

  • 腐蚀
  • 膨胀。

基于这两个操作,我们可以对图像进行更复杂的转换。这里我们简要讨论OpenCV提供的5种操作

开运算

  • 开运算是通过对图像进行腐蚀后,再进行膨胀得到的。

    \[dst = open( src, element) = dilate( erode( src, element ) )\]

  • 用于移除小物体(假设物体在暗背景上是亮的)
  • 例如,请看下面的示例。左侧图像是原始图像,右侧图像是应用开运算转换后的结果。我们可以观察到小点已经消失了。

闭运算

  • 闭运算是通过对图像进行膨胀后,再进行腐蚀得到的。

    \[dst = close( src, element ) = erode( dilate( src, element ) )\]

  • 用于移除小孔(暗区域)。

形态学梯度

  • 它是图像膨胀与腐蚀之间的差异。

    \[dst = morph_{grad}( src, element ) = dilate( src, element ) - erode( src, element )\]

  • 它有助于找到物体的轮廓,如下所示

顶帽

  • 它是输入图像与其开运算之间的差异。

    \[dst = tophat( src, element ) = src - open( src, element )\]

黑帽

  • 它是闭运算与其输入图像之间的差异

    \[dst = blackhat( src, element ) = close( src, element ) - src\]

代码

解释

  1. 让我们看看C++程序的总体结构
    • 加载图像
    • 创建一个窗口来显示形态学操作的结果
    • 创建三个滑动条供用户输入参数
      • 第一个滑动条Operator返回要使用的形态学操作类型(morph_operator)。
        createTrackbar("操作符:\n 0: 开运算 - 1: 闭运算 \n 2: 梯度 - 3: 顶帽 \n 4: 黑帽", window_name, &morph_operator, max_operator, Morphology_Operations );
      • 第二个滑动条Element返回morph_elem,它指示我们的核是什么类型的结构
        createTrackbar( "元素:\n 0: 矩形 - 1: 十字形 - 2: 椭圆形 - 3: 菱形", window_name,
        &morph_elem, max_elem,
        Morphology_Operations );
      • 最后一个滑动条Kernel Size返回要使用的核的大小(morph_size
        createTrackbar( "核大小:\n 2n +1", window_name,
        &morph_size, max_kernel_size,
        Morphology_Operations );
    • 每次我们移动任何滑动条时,都会调用用户函数Morphology_Operations来执行新的形态学操作,并根据当前的滑动条值更新输出图像。

      void Morphology_Operations( int, void* )
      {
      // 由于 MORPH_X : 2,3,4,5 和 6
      int operation = morph_operator + 2;
      Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
      morphologyEx( src, dst, operation, element );
      imshow( window_name, dst );
      }

      我们可以观察到执行形态学转换的关键函数是 cv::morphologyEx 。在这个例子中,我们使用了四个参数(其余使用默认值)

      • src : 源(输入)图像
      • dst: 输出图像
      • operation: 要执行的形态学转换类型。请注意,我们有5种选择

        • 开运算: MORPH_OPEN : 2
        • 闭运算: MORPH_CLOSE: 3
        • 梯度: MORPH_GRADIENT: 4
        • 顶帽: MORPH_TOPHAT: 5
        • 黑帽: MORPH_BLACKHAT: 6

        如您所见,这些值的范围是<2-6>,这就是为什么我们将滑动条输入的值加(+2)。

        int operation = morph_operator + 2;
      • element: 要使用的核。我们使用函数 cv::getStructuringElement 来定义我们自己的结构。

结果

  • 编译上述代码后,我们可以通过提供图像路径作为参数来执行它。使用图像 baboon.png 的结果:
  • 这里是显示窗口的两个截图。第一张图片显示了使用开运算操作符和十字形核的结果。第二张图片(右侧)显示了使用黑帽操作符和椭圆形核的结果。