zoukankan      html  css  js  c++  java
  • 【 imgproc 模块. 图像处理】形态学变化

    一、更多的形态学变化

        包括开运算 (Opening)、闭运算 (Closing)、形态梯度 (Morphological Gradient)、顶帽 (Top Hat)、黑帽(Black Hat)。具体可参考《数字图像处理 第三版》(冈萨雷斯)——第九章 形态学图像处理注:具体原理都是一些数学计算公式、方法,目前只大概了解,后面可具体研读。

    二、开运算

    (1)教程中的解释:

    • 开运算是通过先对图像腐蚀再膨胀实现的。

      dst = open( src, element) = dilate( erode( src, element ) )

    • 能够排除小团块物体(假设物体较背景明亮)

    • 请看下面,左图是原图像,右图是采用开运算转换之后的结果图。 观察发现字母拐弯处的白色空间消失。

      Opening

    (2)资料整理

            开运算和闭运算都由腐蚀和膨胀复合而成, 开运算是先腐蚀后膨胀, 而闭运算是先膨胀后腐蚀。膨胀:亮区扩大;腐蚀:亮区缩小。

                  

           一般来说, 开运算可以使图像的轮廓变得光滑, 还能使狭窄的连接断开和消除细毛刺。 
    如图8.11所示, 开运算断开了团中两个小区域间两个像素宽的连接〈断开了狭窄连接〉,并且去除了右侧物体上部突出的一个小于结构元素的2×2的区域〈去除细小毛刺〉: 但与腐蚀不同的是, 图像大的轮廓并没有发生整体的收缩, 物体位置也没有发生任何变化。 

     (3)opencv代码实现

    #include"stdafx.h"
    #include<opencv2/opencv.hpp>
    int open_value = 0;
    int open_max = 5;
    int morph_elem = 0;
    int max_elem = 2;
    cv::Mat src,dst;
    void openOperator(int,void*);
    
    int main(int argc, char** argv) {
        src = cv::imread("lena512color.tiff");
        if (src.empty()) {
            printf("Image load failed...");
            return -1;
        }
        cv::namedWindow("src", CV_WINDOW_NORMAL);
        cv::createTrackbar("Opening_value:","src", &open_value, open_max, openOperator);
        cv::createTrackbar("Element:
     0: Rect - 1: Cross - 2: Ellipse", "src",&morph_elem, max_elem,openOperator);
        openOperator(0, 0); //这句注释掉时,刚开始运行时若不移动滑动条则图片不会显示
        cvWaitKey(0);
        return 0;
    }
    
    void openOperator(int, void*) {
        /*getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));
        @用法:返回一个特定形状(shape),大小(size),及锚点(anchor)的核,锚点为(-1,-1)时默认为中心
        @参数:int shape     MORPH_RECT    = 0, MORPH_CROSS   = 1, MORPH_ELLIPSE = 2 
        */
        cv::Mat element = cv::getStructuringElement(morph_elem, cv::Size(2 * open_value + 1, 2 * open_value + 1), cv::Point(open_value, open_value));
        morphologyEx(src, dst, cv::MORPH_OPEN, element);//element 为输入的结构元,用于卷积的矩阵
        /*@API:void morphologyEx( InputArray src, OutputArray dst,
                                    int op, InputArray kernel,
                                    Point anchor = Point(-1,-1), int iterations = 1,
                                    int borderType = BORDER_CONSTANT,
                                    const Scalar& borderValue = morphologyDefaultBorderValue() );   
          @用法:
          @参数:op形态学操作类型
        MORPH_ERODE    = 0,  MORPH_DILATE   = 1,  MORPH_OPEN     = 2,  MORPH_CLOSE    = 3,
              MORPH_GRADIENT = 4, MORPH_TOPHAT   = 5, MORPH_BLACKHAT = 6,  MORPH_HITMISS  = 7
          @参数:InputArray kernel,用于进行形态学操作的核,可以用getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));获取
          @参数:anchor,锚点,核的锚点位置,默认(-1,-1)则为中心
          @参数:iterations,腐蚀、膨胀次数次数
          @参数:borderType,参数外推方法,
          ...具体用到再查*/  
        cv::imshow("src", dst);
    }

    二、闭运算

    (1)教程中的解释:

    • 闭运算是通过先对图像膨胀再腐蚀实现的。

      dst = close( src, element ) = erode( dilate( src, element ) )

    能够排除小型黑洞(黑色区域)。

    Closing example

    (2)相关资料整理:

    闭运算同样可以使轮廓变得光滑, 但与开运算相反, 它通常能够弥合狭窄的间断, 填充小的孔洞。

     (3)opencv实现代码:类似开运算

    三、形态梯度

    • 膨胀图与腐蚀图之差

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

    • 能够保留物体的边缘轮廓,如下所示:

      Gradient

    四、顶帽

    • 原图像与开运算结果图之差
    • dst = tophat( src, element ) = src - open( src, element )

         Top Hat

    五、黑帽

    • 闭运算结果图与原图像之差

      dst = blackhat( src, element ) = close( src, element ) - src

      Black Hat

    六、测试代码(官方)

    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include <stdlib.h>
    #include <stdio.h>
    
    using namespace cv;
    
    /// 全局变量
    Mat src, dst;
    
    int morph_elem = 0;
    int morph_size = 0;
    int morph_operator = 0;
    int const max_operator = 4;
    int const max_elem = 2;
    int const max_kernel_size = 21;
    
    char* window_name = "Morphology Transformations Demo";
    
    /** 回调函数申明 */
    void Morphology_Operations( int, void* );
    
    /** @函数 main */
    int main( int argc, char** argv )
    {
      /// 装载图像
      src = imread( argv[1] );
    
      if( !src.data )
      { return -1; }
    
     /// 创建显示窗口
     namedWindow( window_name, CV_WINDOW_AUTOSIZE );
    
     /// 创建选择具体操作的 trackbar
     createTrackbar("Operator:
     0: Opening - 1: Closing 
     2: Gradient - 3: Top Hat 
     4: Black Hat", window_name, &morph_operator, max_operator, Morphology_Operations );
    
     /// 创建选择内核形状的 trackbar
     createTrackbar( "Element:
     0: Rect - 1: Cross - 2: Ellipse", window_name,
                     &morph_elem, max_elem,
                     Morphology_Operations );
    
     /// 创建选择内核大小的 trackbar
     createTrackbar( "Kernel size:
     2n +1", window_name,
                     &morph_size, max_kernel_size,
                     Morphology_Operations );
    
     /// 启动使用默认值
     Morphology_Operations( 0, 0 );
    
     waitKey(0);
     return 0;
     }
    
     /**
      * @函数 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 );
      }
    One day,I will say "I did it"
  • 相关阅读:
    隐藏滚动条但可用滚动
    封装axios,带请求头和响应头
    文本超出显示...
    设置vue-quill-editor禁止输入或编辑
    element-ui select多选情况下获取label和value
    处理vue-quill-editor回显数据的时候没有空格问题
    Redis学习之路(二)Redis集群搭建
    redis requires Ruby version >= 2.2.2问题
    Redis学习之路(一)Redis简介
    Logstash学习之路(五)使用Logstash抽取mysql数据到kakfa
  • 原文地址:https://www.cnblogs.com/Vince-Wu/p/10076240.html
Copyright © 2011-2022 走看看