二、形态学操作腐蚀、膨胀、开运算、闭运算、形态学梯度、顶帽、黑帽

时间:2024-05-20 08:43:22

 

一、腐蚀、膨胀、开运算、闭运算的作用与定义:

  1. 腐蚀的作用是消除物体边界点,使目标缩小,可以消除小于结构元素的噪声点;
  2. 膨胀的作用是将与物体接触的所有背景点合并到物体中,使目标增大,可添补目标中的空洞。  
  3. 开运算是先腐蚀后膨胀的过程,可以消除图像上细小的噪声,并平滑物体边界。  
  4. 闭运算时先膨胀后腐蚀的过程,可以填充物体内细小的空洞,并平滑物体边界。 

在OpenCV中几乎所有的操作都是针对图像的像素点进行的,包括灰化,二值化,模糊化等,膨胀和腐蚀也是一样,都是针对传入图像的像素点进行操作的!!!

膨胀: 
此操作将图像(A)与任意形状的内核 (B),通常为正方形或圆形,进行卷积。内核 B 有一个可定义的 锚点, 通常定义为内核中心点。进行膨胀操作时,将内核 B 划过图像,将内核 B 覆盖区域的最大相素值提取,并代替锚点位置的相素。显然,这一最大化操作将会导致图像中的亮区开始”扩展” (因此有了术语膨胀 dilation )。 
这种操作会造成图像中像素值高的区域变大,而像素值小的区域变小,等一下看你一下效果你就知道了!!!

腐蚀: 
跟膨胀操作造作的效果刚好相反。腐蚀在形态学操作家族里是膨胀操作的孪生姐妹。它提取的是内核覆盖下的相素最小值。进行腐蚀操作时,将内核 B 划过图像,将内核 B 覆盖区域的最小相素值提取,并代替锚点位置的相素。以与膨胀相同的图像作为样本,我们使用腐蚀操作。从下面的结果图我们看到亮区(背景)变细,而黑色区域(字母)则变大了。

总结

  1. 腐蚀(erode),是将灰度值小(视觉上就是比较暗)的区域增强扩展,主要用来去除比较亮的噪点。
  2. 膨胀(dilate),是将灰度值大(视觉上就是比较亮)的区域增强扩展,主要用来连通相似颜色或强度的区域。

含义,顺便利用opencv实现一下,看看具体效果。

二、腐蚀和膨胀原理分析:

腐蚀与膨胀涉及的一个重要概念就是核,也可以称之为模板或者掩码。核具有几个重要的属性,形状(圆形、方形、十字架甚至椭圆),大小(3x3,5x5等)以及参考点。多数情况下,模板比较简单的是一个圆形,大小3x3,参考点在圆心。如下图所示: 
二、形态学操作腐蚀、膨胀、开运算、闭运算、形态学梯度、顶帽、黑帽 
不同的腐蚀与膨胀算法,本质的区别在于核的设计,如果你的核设计与你的图像场景以及相关目的比较吻合时,效果也许就会好。

具体机理其实很简单,拿腐蚀来说(因为膨胀就是腐蚀的对偶操作,两者流程本质上没有区别)。你确定好核以后,就与原图像进行卷积。原图像的每个像元的灰度值等于,以该像元为参考点,核所覆盖的范围内,所有像元的灰度最小值,这样就完成了腐蚀操作。膨胀操作就是取最大值。

所以腐蚀膨胀的内容很简单,下面主要讲一讲opencv中提到的cvMorphologyEx()这个函数。该函数主要针对的是灰度或者彩色图像。cvMorphologyEx(const CvArr* src,CvArr* dst,CvArr* temp, IplConvKernel* element, int operation,int iterations=1)的函数原型是这样,其中的operation涉及到了5中运算,分别是开运算,闭运算,形态梯度,礼帽,黑帽。下面我主要说说这几种的具体含义,顺便利用opencv实现一下,看看具体效果。

三、开运算与闭运算:

两种就是膨胀腐蚀的连接。

  1. 开运算先进行腐蚀再进行膨胀,主要是可以消除高于其邻近点的孤立点。下图就可以看出 
    二、形态学操作腐蚀、膨胀、开运算、闭运算、形态学梯度、顶帽、黑帽
  2. 闭运算先进行膨胀再进行腐蚀,主要是可以消除低于其邻近点的孤立点。下图就可以看出 
    二、形态学操作腐蚀、膨胀、开运算、闭运算、形态学梯度、顶帽、黑帽

 

参考:https://blog.****.net/u013207865/article/details/49363921

 

三、形态学梯度、顶帽、黑帽

1、形态学梯度Morphological Gradient:膨胀减去腐蚀

2、顶帽 是原图像与开操作之间的差值图像

3、黑帽是闭操作图像与源图像的差值图像

三、Opencv中的API实现

去参考https://blog.****.net/keen_zuxwang/article/details/72768092

1、腐蚀和膨胀的Opencv实现

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;

Mat src, dst;
char OUTPUT_WIN[] = "ouptut_image";
int element_size = 3;
int max_size = 21;
void CallBack_Demo(int, void*);
int main(int argc, char** argv) {
    src = imread("C:/Users/maker/Pictures/website/img1.png");
    if (!src.data) {
        printf("could not load image\n");
    }
    namedWindow("input_image",CV_WINDOW_AUTOSIZE);
    imshow("input_image", src);

    namedWindow(OUTPUT_WIN, CV_WINDOW_AUTOSIZE);
    createTrackbar("ElementSize:", OUTPUT_WIN,&element_size, max_size,CallBack_Demo);
    //createTrackbar是Opencv中的API,可在图像窗口中创建一个滑动控件,用于手动调节阈值
    //createTrackbar(const string& trackbarname, const string& winname,int* value, 
    //int count,TrackbarCallback onChange = 0,void* userdata = 0);
    //参数一、trackbarname:滑动空间的名称;
    //参数二、winname:滑动空间用于依附的图像窗口的名称;
    //参数三、value:初始化阈值;
    //参数四、count:滑动控件的刻度范围;
    //参数五、TrackbarCallback是回调函数,其定义如下:
    //typedef void (CV_CDECL *TrackbarCallback)(int pos, void* userdata);

    CallBack_Demo(0, 0);
    waitKey(0);
    return 0;
}

void CallBack_Demo(int, void*) {
    int s = element_size * 2 + 1;
    Mat structureElement = getStructuringElement(MORPH_RECT,Size(s,s),Point(-1,-1));
    dilate(src, dst, structureElement, Point(-1, -1), 1); //腐蚀
    //erode(src,dst,structureElement); //膨胀
    imshow(OUTPUT_WIN, dst);
    return;

}

 

二、形态学操作腐蚀、膨胀、开运算、闭运算、形态学梯度、顶帽、黑帽

 

二、形态学操作腐蚀、膨胀、开运算、闭运算、形态学梯度、顶帽、黑帽

2、Opencv开运算、闭运算、顶帽、黑帽

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
int main(int argc, char** argv) {
    Mat src, dst;
    src = imread("D:/vcprojects/images/bin2.png");
    if (!src.data) {
        printf("could not load image...\n");
    }
    namedWindow("input image", CV_WINDOW_AUTOSIZE);
    imshow("input image", src);
    char output_title[] = "morphology demo";
    namedWindow(output_title, CV_WINDOW_AUTOSIZE);

    Mat kernel = getStructuringElement(MORPH_RECT, Size(11, 11), Point(-1, -1));
    morphologyEx(src, dst, CV_MOP_BLACKHAT, kernel);
    imshow(output_title, dst);

    waitKey(0);
    return 0;
}