OpenCV  4.10.0
开源计算机视觉
加载中...
搜索中...
没有匹配项
更多形态变换

上一篇教程: 腐蚀和膨胀
下一篇教程: 命中或不命中

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

目标

本教程中您将学习如何

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

理论

注意
以下说明来自 Bradski 和 Kaehler 合著的书《学习 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++ 程序的总体结构
    • 加载图像
    • 创建一个窗口显示形态学操作的结果
    • 创建三个轨迹条让用户输入参数
      • 第一个轨迹条运算符返回要使用的形态学操作的类型 (morph_operator)。
        createTrackbar("算子:\n 0:开运算 - 1:闭运算 \n 2:梯度 - 3:顶帽 \n 4:底帽", window_name, &morph_operator, max_operator, Morphology_Operations );
      • 第二个轨迹条元素返回 morph_elem,表示我们的内核是什么类型的结构
        createTrackbar( "元素:\n 0:矩形 - 1:十字 - 2:椭圆", window_name,
        &morph_elem, max_elem,
        Morphology_Operations );
      • 最后一个轨迹条内核大小返回要使用的内核大小 (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
  • 以下是显示窗口的两个快照。第一张图片显示使用十字架内核的开口算子后的输出。第二张图片(右侧)显示了使用椭圆内核的黑顶帽算子的结果。