zoukankan      html  css  js  c++  java
  • 形态学滤波(2):开运算、闭运算、形态学梯度、顶帽、黑帽

    一、开运算

    开运算,就是先腐蚀后膨胀的过程

    数学表达式:

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

    开运算可以用来消除小物体,在纤细点处分离物体,并且在平滑较大物体的边界的同时不明显改变其面积。

    二、闭运算

    闭运算,就是先膨胀后腐蚀的过程

    数学表达式:

      dst = open(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 

    黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关

    黑帽运算用来分离比临近点暗一些的斑块,效果图有着非常完美的轮廓

    六、核心函数:morphologyEx()

    1 void morphologyEx( InputArray src, OutputArray dst,
    2                                 int op, InputArray kernel,
    3                                 Point anchor = Point(-1,-1), int iterations = 1,
    4                                 int borderType = BORDER_CONSTANT,
    5                                 const Scalar& borderValue = morphologyDefaultBorderValue() );

      1 #include<opencv2/opencv.hpp>
      2 #include<iostream>
      3 
      4 using namespace std;
      5 using namespace cv;
      6 
      7 Mat g_srcImage, g_dstImage;
      8 int g_nElementShap = MORPH_RECT;   //元素结构的形状
      9 
     10 //变量接收的TrackBar位置参数
     11 int g_nMaxIterationNum = 10;
     12 int g_nOpenCloseNum = 0;
     13 int g_nErodeDilateNum = 0;
     14 int g_nTopBlackHatNum = 0;
     15 
     16 static void on_OpenClose(int, void *);   //回调函数
     17 static void on_ErodeDilate(int, void *);
     18 static void on_TopBlackHat(int, void *);
     19 
     20 
     21 int main()
     22 {
     23     //载入原图
     24     g_srcImage = imread("C:\Users\Administrator\Pictures\Camera Roll\05.jpg");
     25     if (!g_srcImage.data) {
     26         cout << "图片载入失败!" << endl;
     27         return false;
     28     }
     29 
     30     //显示原始图
     31     namedWindow("【原始图】");
     32     imshow("【原始图】", g_srcImage);
     33 
     34     //创建三个窗口
     35     namedWindow("【开运算/闭运算】", 1);
     36     namedWindow("【腐蚀/膨胀】", 1);
     37     namedWindow("【顶帽/黑帽】", 1);
     38 
     39     //分别为三个窗口创建滚动条
     40     createTrackbar("迭代值", "【开运算/闭运算】", &g_nOpenCloseNum, g_nMaxIterationNum * 2 + 1, on_OpenClose);
     41     createTrackbar("迭代值", "【腐蚀/膨胀】", &g_nErodeDilateNum, g_nMaxIterationNum * 2 + 1, on_ErodeDilate);
     42     createTrackbar("迭代值", "【顶帽/黑帽】", &g_nTopBlackHatNum, g_nMaxIterationNum * 2 + 1, on_TopBlackHat);
     43 
     44     //轮询获取按键信息
     45     while (1)
     46     {
     47         int c;
     48 
     49         //执行回调函数
     50         on_OpenClose(g_nOpenCloseNum, 0);
     51         on_ErodeDilate(g_nErodeDilateNum, 0);
     52         on_TopBlackHat(g_nTopBlackHatNum, 0);
     53 
     54         //获取按键
     55         c = waitKey(0);
     56 
     57         //按下键盘Q或者ESC,程序退出
     58         if (c == 'q' || c == 27)
     59             break;
     60         //按下键盘按键1,使用椭圆(Elliptic)结构元素MORPH_ELLIPSE
     61         if (c == 'a')
     62             g_nElementShap = MORPH_ELLIPSE;
     63         //按下键盘按键2,使用矩形(Rectangle)结构元素MORPH_RECT
     64         if (c == 'b')
     65             g_nElementShap = MORPH_RECT;
     66         //按下键盘按键3,使用十字形(Cross-shaped)结构元素MORPH_CROSS
     67         if (c == 'c')
     68             g_nElementShap = MORPH_CROSS;
     69         //按下键盘按键space,在矩形、椭圆、十字形结构元素中循环
     70         if (c == ' ')
     71             g_nElementShap = (g_nElementShap + 1) % 3;
     72     }
     73     return 0;
     74 }
     75     static void on_OpenClose(int, void *) {
     76         //偏移量的定义
     77         int offset = g_nOpenCloseNum - g_nMaxIterationNum;  //偏移量
     78         int Absolute_offset = offset > 0 ? offset : -offset;  //偏移量的绝对值
     79         //自定义核
     80         Mat element = getStructuringElement(g_nElementShap, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
     81 
     82         //进行操作
     83         if (offset < 0)
     84             morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);
     85         else
     86             morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);
     87 
     88         //显示图像
     89         imshow("【开运算/闭运算】", g_dstImage);
     90     }
     91 
     92     static void on_ErodeDilate(int, void *) {
     93         int offset = g_nOpenCloseNum - g_nMaxIterationNum;  //偏移量
     94         int Absolute_offset = offset > 0 ? offset : -offset;  //偏移量的绝对值
     95         //自定义核
     96         Mat element = getStructuringElement(g_nElementShap, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
     97 
     98         //进行操作
     99         if (offset < 0)
    100             erode(g_srcImage, g_dstImage, element);
    101         else
    102             dilate(g_srcImage, g_dstImage, element);
    103 
    104         //显示图像
    105         imshow("【腐蚀/膨胀】", g_dstImage);
    106     }
    107 
    108     static void on_TopBlackHat(int, void *) {
    109         int offset = g_nOpenCloseNum - g_nMaxIterationNum;  //偏移量
    110         int Absolute_offset = offset > 0 ? offset : -offset;  //偏移量的绝对值
    111         //自定义核
    112         Mat element = getStructuringElement(g_nElementShap, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
    113 
    114         //进行操作
    115         if (offset < 0)
    116             morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);
    117         else
    118             morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);
    119 
    120         //显示图像
    121         imshow("【顶帽/黑帽】", g_dstImage);
    122     }
    123     
  • 相关阅读:
    【问题备注】VS2012不能输入代码,文字…
    犯错了又
    关于实习…
    百度2014校招笔试题目题解(更新了第1题的算法,10.9下午)
    人人校招笔试题
    腾讯2014软件开发笔试题目
    阿里巴巴笔试题选解
    批处理文件——多个QQ一键登录
    动态规划---LIS
    动态规划--凑硬币问题
  • 原文地址:https://www.cnblogs.com/Nelsoner/p/6783477.html
Copyright © 2011-2022 走看看