【计算机视觉】形态学滤波

【计算机视觉】形态学滤波

标签(空格分隔): 【图像处理】 【信号处理】

版权声明:本文为博主原创文章,转载请注明出处http://blog.csdn.net/lg1259156776/



说明:本文主要想弄清楚形态学滤波在图象处理和信号处理中的应用,图像处理中非常直观的通过腐蚀膨胀获得开闭运算的效果,而在数据实时滤波中,形态学滤波也是可以使用的。


形态学滤波基本知识

原理:在特殊领域运算形式——结构元素(Sturcture Element),在每个像素位置上与二值图像对应的区域进行特定的逻辑运算。运算结构是输出图像的相应像素。运算效果取决于结构元素大小内容以及逻辑运算性质。

膨胀、腐蚀、开、闭运算是数学形态学最基本的变换。

结构元素简单地定义为像素的结构(形状)以及一个原点(又称为锚点),使用形态学滤波涉及对图像的每个像素应用这个结构元素,当结构元素的原点与给定的像素对齐时,它与图像相交部分定义了一组进行形态学运算的像素。原则上,结构元素可以是任何形状,但通常使用简单的形状,比如方形、圆形和菱形,而原点位于中心位置(基于效率的考虑)。

腐蚀和膨胀两个滤波操作也运算在每个像素周围像素集合上(邻域),这是由结构元素定义的。当应用到一个给定的像素时,结构元素的锚点与该像素的位置对齐,而所有与他相交的像素都被包括在当前像素集合中。腐蚀替换当前像素为像素集合中找到的最小的像素值,而膨胀则替换为像素集合中找到的最大像素值。当然,对于二值图像,每个像素只能被替换为白色像素或黑色像素。

这一段的论述,可以参考Opencv计算机视觉 编程手册。对于腐蚀和膨胀的差别,可以通过想象,腐蚀呢, 如果给定像素的结构元素触碰到背景,那么该像素被设置为背景,而在膨胀的情况下,如果触碰到前景,该像素被设置为前景,所以很明显,腐蚀操作后物体的尺寸会减小,而膨胀操作后物体的尺寸会增大,同时内部的一些洞被填满。

事实上,腐蚀一副图像两次,就像是让结构元素对自己进行膨胀后再去腐蚀同一幅图像;反过来对膨胀也是合适的。

有下面两种说法:

  1. 对图像的腐蚀操作等于对图像负片的膨胀操作的负片;
  2. 对图像的膨胀操作等于对图像负片的腐蚀操作的负片;

实际上说的是对目标进行的腐蚀,等效于对背景进行的膨胀;反之亦然。

腐蚀的最简单的应用是从图中消除不相关的细节,而膨胀的最简单的应用是将裂缝桥接起来。开运算是先腐蚀再膨胀,开运算一般断开狭窄的间断和消除细的突出物,而闭操作通常消弥狭窄的间断和长细的鸿沟,消除小的孔洞,并填充轮廓线中的断裂。开运算与闭运算的结合使用能使作用对象的轮廓变得光滑

开运算是先腐蚀再膨胀,而闭运算是先膨胀再腐蚀;

在检验闭滤波器的结果时,可以看到白色前景物体中的小洞被填充,该滤波器同时连接多个相邻物体,基本上,无法完全包含结构元素的洞洞或者缝隙都将被滤波器移除。反过来,开滤波器则是移除掉场景中比较小的物体,因为它门无法完全包含结构元素。

这些滤波器通常在物体检测中应用,闭滤波器将误分割为碎片的物体重新连接起来,而开滤波器则去除掉图像噪声点引起的小像素块(Blob)。因此,在视频序列中使用他们很有帮助,如果测试的二值图像相继使用闭、开操作,获得图像将只显示场景中的主要物体。如果优先处理噪点,也可以先进行开运算,再进行闭运算,但是有可能去除掉一些分散的物体。

需要注意的是,对于对于一幅图像多次使用相同的开运算或者闭运算是没有效果的,因为在第一次闭(开)运算填充图像中的洞洞后,再次应用相同的滤波,不会对图像产生任何变化。用数学的术语讲,这些运算是等幂的。

使用形态学滤波对图像进行边缘及角点检测

形态学滤波可以用于检测图像中指定的特征。

一种比较形象的方法是将灰度图像看做是“等高线”(比如分水岭图像分割算法):亮的区域代表山峰,而暗的区域代表山谷,图像的边沿就对应于峭壁。如果腐蚀一幅图像,会导致山谷被扩展,而峭壁减少了。相反的,如果膨胀一幅图像,峭壁则会增加。但是这两种情况下,中间的部分(大片的谷底和高原)基本保持不变。

在上述理解的基础上,如果我们对图像的腐蚀和膨胀的结果做差,就能提取图像的边界:因为边界区域,二者完全不同。(实际上,我们也可以用腐蚀或者膨胀的结果与源图像做差得出类似结果,但提取的边界会比较细)。可以看出,结构元越大,边界越粗。在OpenCV中,将形态学操作函数morphologyEx 的第4个参数设为MORPH_GRADIENT,就能完成上述工作。

利用形态学操作获取角点稍微有一些复杂,它试用了四种不同的结构元素,基本方法是对一幅图像先腐蚀,在膨胀但是这两次操作使用的结构元却不同。这些结构元的选取使得直线保持不变,但是由于他们各自作用的效果,角点处的边沿被影响了。我们结合一幅图来说明:

第一幅图是原图。在被十字形元素膨胀后,方块的边缘被扩张,而由于十字形元素没有击中角点,此处不受影响。中间的方块描述了这个结果;膨胀后的图像接着被菱形元素腐蚀,这次运算将大多数的边缘恢复到原始位置,但之前没有膨胀过的角点被向内推动,之后得到了左边的方块,可以看到,他缺少明显的角点。同样的处理过程通过X形与方形元素得到重复。这两个元素结构是先前元素的旋转版本,捕获的将是45°旋转后的角点。最后,对两次过程的结果做差值,提取角点特征。

代码可以参考参考文献3.

形态学滤波之图象处理

一般腐蚀操作对二值图进行处理,腐蚀操作如下图,中心位置的像素点是否与周围领域的像素点颜色一样(即是否是白色点,即值是否为255),若一致,则保留,不一致则该点变为黑色(值即为0)

opencv中的腐蚀操作:

CVAPI(void)  cvErode( const CvArr* src, CvArr* dst,
                      IplConvKernel* element CV_DEFAULT(NULL),
                      int iterations CV_DEFAULT(1) );

前两个参数比较熟悉,第三个参数是用于传递模板的信息,默认是(NULL),即为3*3的模板,第四个参数是迭代的次数(即该腐蚀操作做几次);

opencv中的膨胀操作其实就是腐蚀的反操作:

CVAPI(void)  cvDilate( const CvArr* src, CvArr* dst,
                       IplConvKernel* element CV_DEFAULT(NULL),
                       int iterations CV_DEFAULT(1) );

测试代码:

#include “stdafx.h”

#include “cv.h”

#include “highgui.h”

int main(){
    IplImage *img= cvLoadImage("C:/fu.jpg");//读取图片
    cvNamedWindow("Example1",CV_WINDOW_AUTOSIZE);
    cvNamedWindow("Example2",CV_WINDOW_AUTOSIZE);
    cvNamedWindow("Example3",CV_WINDOW_AUTOSIZE);

    cvShowImage("Example1",img);//在Example1显示图片
    //    cvCopy(img,temp);
    IplImage* temp=cvCreateImage( //创建一个size为image,三通道8位的彩色图
        cvGetSize(img),
        IPL_DEPTH_8U,
        3
        );

    cvErode(img,temp,0,1);//腐蚀
    cvShowImage("Example2",temp);

    cvDilate(img,temp,0,1);//膨胀
    cvShowImage("Example3",temp);

    cvWaitKey(0);//暂停用于显示图片

    cvReleaseImage(&img);//释放img所指向的内存空间并且
    cvDestroyWindow("Example1");
    cvDestroyWindow("Example2");
    cvDestroyWindow("Example3");

    return 0;
}

以上都是在模板3*3的情况下处理的,要是我们期望使用自己定义的模板时候,就需要自己做模板。

CVAPI(IplConvKernel*)  cvCreateStructuringElementEx(
            int cols, int  rows, int  anchor_x, int  anchor_y,
            int shape, int* values CV_DEFAULT(NULL) );

前两个参数是定义模板的大小,后两个参数是参考点的坐标(比如默认3*3模板的参考点坐标是2*2),第五个参数是模板的类型(可以是矩形,十字形,椭圆形,甚至是用户自己定义形状),最后一个参数是在使用自自定义形状的时候,通过value传递模板的形状。

模板的类型:

CVAPI(void)  cvReleaseStructuringElement( IplConvKernel** element ); //释放模板所占用的内存

自定义5*5,参考点(3,3)的矩形模板的测试代码:

#include "stdafx.h"
#include "cv.h"
#include "highgui.h"

int main(){
    IplImage *img= cvLoadImage("C:/fu.jpg");//读取图片
    cvNamedWindow("Example1",CV_WINDOW_AUTOSIZE);
    cvNamedWindow("Example2",CV_WINDOW_AUTOSIZE);
    cvNamedWindow("Example3",CV_WINDOW_AUTOSIZE);

    cvShowImage("Example1",img);//在Example1显示图片
    //    cvCopy(img,temp);
    IplImage* temp=cvCreateImage( //创建一个size为image,三通道8位的彩色图
        cvGetSize(img),
        IPL_DEPTH_8U,
        3
        );

    IplConvKernel * myModel;
    myModel=cvCreateStructuringElementEx( //自定义5*5,参考点(3,3)的矩形模板
        5,5,2,2,CV_SHAPE_RECT
        );

    cvErode(img,temp,myModel,1);
    cvShowImage("Example2",temp);

    cvDilate(img,temp,myModel,1);
    cvShowImage("Example3",temp);

    cvWaitKey(0);//暂停用于显示图片

    cvReleaseStructuringElement(&myModel);
    cvReleaseImage(&img);//释放img所指向的内存空间并且
    cvDestroyWindow("Example1");
    cvDestroyWindow("Example2");
    cvDestroyWindow("Example3");

    return 0;
}

效果图:

形态学滤波之信号处理

数学形态学的方法可以理解为一个具有一定直径的小球滚过一段特定的路径,各种信号可以看作是路径上的小坑。由于所有的噪声都有个共同特征一一高频低峰(它们构成非常复杂,由各种混合在眼电信号中的其他成份或眼球快速、微小、空间大小不超过1“的运动导致),这些小坑的径长明显小于小球直径,因此小球球心的滚动轨迹不会受噪声的干扰一一小球球心滚动轨迹即可以看成数学形态学处理后的信号。本系统中用到的数学形态学算子包括腐蚀运算、膨胀运算、开操作、闭操作。

腐蚀的最简单的应用是从图中消除不相关的细节,而膨胀的最简单的应用是将裂缝桥接起来。开运算是先腐蚀再膨胀,开运算一般断开狭窄的间断和消除细的突出物,而闭操作通常消弥狭窄的间断和长细的鸿沟,消除小的孔洞,并填充轮廓线中的断裂。开运算与闭运算的结合使用能使作用对象的轮廓变得光滑

#include <stdio.h>
#include <fcntl.h>
//#include <sys/types.h>
//#include <sys/stats.h>
#include <time.h>
#define N 5  //结构元素。大小设置根据滤除波形一个周期中点个数来定。例如:采样率250,滤除50hz,
                                                                 //因为50hz一个周期中有5个点,所以N设为5。          

float x[3*N+2]={0.0};

void openoperate(float input[],float dilation[]) //开运算:先腐蚀再膨胀
{
    int i,k,t;
    float tmp;
    t=2*N+3;
    float erosion[2*N+3];
    for(k=0;k<t;k++){
        tmp=input[k];
        for(i=k+1;i<k+N;i++){
            if(tmp>input[i])
                tmp=input[i];
        }
        erosion[k]=tmp;
    }
    t=t-3;
    for(k=0;k<t;k++){
        tmp=erosion[k];
        for(i=k+1;i<k+N;i++){
            if(tmp<erosion[i])
                tmp=erosion[i];
        }
        dilation[k]=tmp;
    }
}

float closeoperate(float input[]) //闭运算:先膨胀再腐蚀
{
    int i,k,t;
    float tmp;

    t=N*2-1;
    float dilation[N];

    for(k=0;k<N;k++){
        tmp=input[k];
        for(i=k+1;i<k+N;i++){
            if(tmp<input[i])
                tmp=input[i];
        }
        dilation[k]=tmp;
    }

    tmp=dilation[0];
    for(k=1;k<N;k++){
        if(tmp>dilation[k])
            tmp=dilation[k];
    }
    return tmp;
}

int main()
{
    clock_t start,end;
    double duration;
    FILE *fd,*m_fd;
    float buffer;
    float filter_data;
    float openresult[2*N-1];

    m_fd=fopen("D:/data.txt","r+");
    if(m_fd==NULL){
        perror("open error!");
        return -1;
    }

    fd=fopen("D:/data1.txt","w+");
    if(fd==NULL){
        perror("open error!");
        return -1;
    }
    start=clock();
    while(fscanf(m_fd,"%f",&buffer)!=EOF){
          x[3*N+1]=buffer;

          openoperate(x,openresult);
          filter_data=closeoperate(openresult);
          fprintf(fd,"%f ",filter_data);

          for(int y=0;y<3*N+1;y++)
               x[y]=x[y+1];
    }
    end=clock();
    duration=(double)(end-start)/CLOCKS_PER_SEC;
    printf("%f seconds\n",duration);
    fclose(fd);
    fclose(m_fd);
    return 0;
}

结果如下图所示,对有干扰原始眼电数据进行形态学滤波处理,其中结构元素17个,窗宽5.有图可以看到,形态学对于尖峰的滤波效果特别明显。

图二,将形态学滤波算法加入Qt中,对眼电进行实时滤波处理,效果如图:

【引】这部分内容主要来自参考文献2

总结

以前认为形态学滤波只在图像处理中有所应用,现在看了参考文献2,才发觉自己实在有点固步自封,对知识的来龙去脉掌握的不够清楚,一言以蔽之,囫囵吞枣,并不清楚思考方向,而只掌握具体的技巧细节,不注重顶层设计,所以才会有此感慨。

在进行数据处理中,常常用到的滤波方法有中值滤波,均值滤波,FIR,IIR,卡尔曼滤波,自适应滤波等。而很多知识都是相符相通的,切不可死学死记。

参考文献:

1. http://blog.csdn.net/thefutureisour/article/details/7574819

2. http://m.blog.csdn.net/blog/gylltq/33799347

3. OpenCV 2 计算机视觉编程手册


2015-11-28 学习笔记 张朋艺

时间: 2024-08-03 00:00:58

【计算机视觉】形态学滤波的相关文章

形态学滤波:(1)腐蚀与膨胀 (2)开运算,闭运算,形态学梯度,顶帽,黑帽

一.形态学概述 图像处理中的形态学一般指的是数学形态学. 数学形态学是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论.其基本运算包括:二值腐蚀和膨胀,二值开闭运算,骨架抽取,极限腐蚀,击中击不中变换,形态学梯度,top-hat变换,颗粒分析,流域变换,灰值腐蚀和膨胀,灰值开闭运算,灰值形态学梯度等. 简单来讲,形态学操作就是基于形状的一系列图像处理操作. 二.形态学滤波 (1)腐蚀与膨胀 膨胀和腐蚀能实现多种多样的功能,主要如下: 消除噪声: 分割(isolate)

[PCL]点云渐进形态学滤波

PCL支持点云的形态学滤波,四种操作:侵蚀.膨胀.开(先侵蚀后膨胀).闭(先膨胀后侵蚀) 在#include <pcl/filters/morphological_filter.h>中定义了枚举类型 1 enum MorphologicalOperators 2 { 3 MORPH_OPEN, 4 MORPH_CLOSE, 5 MORPH_DILATE, 6 MORPH_ERODE 7 }; 具体实现: 1 template <typename PointT> void 2 pcl

python数字图像处理(13):基本形态学滤波

对图像进行形态学变换.变换对象一般为灰度图或二值图,功能函数放在morphology子模块内. 1.膨胀(dilation) 原理:一般对二值图像进行操作.找到像素值为1的点,将它的邻近像素点都设置成这个值.1值表示白,0值表示黑,因此膨胀操作可以扩大白色值范围,压缩黑色值范围.一般用来扩充边缘或填充小的孔洞. 功能函数:skimage.morphology.dilation(image, selem=None) selem表示结构元素,用于设定局部区域的形状和大小. from skimage

形态学滤波(2):开运算、闭运算、形态学梯度、顶帽、黑帽

一.开运算 开运算,就是先腐蚀后膨胀的过程 数学表达式: dst = open(src,element) = dilate(erode(src, element)) 开运算可以用来消除小物体,在纤细点处分离物体,并且在平滑较大物体的边界的同时不明显改变其面积. 二.闭运算 闭运算,就是先膨胀后腐蚀的过程 数学表达式: dst = open(src,element) = erode(dilate(src, element)) 闭运算可以用来排除小型黑洞(黑色区域) 三.形态学梯度 形态学梯度,就是

形态学滤波(3):使用形态学滤波对图像进行边缘及角点检测.

1 #include<opencv2/opencv.hpp> 2 #include<iostream> 3 4 using namespace std; 5 using namespace cv; 6 7 //首先定义MorphoFeatures类,我们将使用它来检测图像特征 8 class MorphoFeatures { 9 private: 10 int threShold; //用于生成二值图像的阈值 11 Mat cross; //角点检测中用到的结构元素 12 Mat

毕业课题之------------图像的形态学滤波

膨胀和腐蚀这两种操作是形态学处理的基础,许多形态学算法都是以这两种运算为基础的. 针对二值化图像 ① 膨胀 是以得到B的相对与它自身原点的映像并且由z对映像进行移位为基础的.A被B膨胀是所有位移z的集合,这样, 和A至少有一个元素是重叠的.我们可以把上式改写为: 结构元素B可以看作一个卷积模板,区别在于膨胀是以集合运算为基础的,卷积是以算术运算为基础的,但两者的处理过程是相似的. ⑴ 用结构元素B,扫描图像A的每一个像素 ⑵ 用结构元素与其覆盖的二值图像做"与"操作 ⑶ 如果都为0,结

形态学滤波(4):使用分水岭算法对图像进行分割

一.分水岭算法 分水岭变换是一个流行的图像处理算法,用于快速分割图像为同类区域.它背后的原理是,将图像视为拓扑结构的地图, 那么均质区域对应的是被陡峭边缘包围的平坦盆地. 实现方法: 分水岭分割的结果是通过watershed()函数获取. 我们将图片中已知属于某个区域的像素进行标记,基于这个标记,分水岭算法开始确定其他像素的归属区域. 1 #include<opencv2/opencv.hpp> 2 #include<iostream> 3 4 using namespace st

OpenCV2学习笔记(三):形态学及边缘角点检测

形态学滤波理论于上世纪90年代提出,目前被广泛用于分析及处理离散图像.其基本运算有4个: 膨胀.腐蚀.开启和闭合, 它们在二值图像和灰度图像中各有特点.基于这些基本运算还可推导和组合成各种数学形态学实用算法,用它们可以进行图像形状和结构的分析及处理,包括图像分割.特征抽取.边缘检测. 图像滤波.图像增强和恢复等.数学形态学方法利用一个称作结构元素的"探针"收集图像的信息,当探针在图像中不断移动时, 便可考察图像各个部分之间的相互关系,从而了解图像的结构特征.数学形态学基于探测的思想,与

OPENCV形态学操作1

形态学操作是指基于形状的一系列图像处理操作,包括膨胀,腐蚀,二值化,开运算,闭运算,顶帽算法,黑帽算法,形态学梯度等,最基本的形态学操作就是膨胀和腐蚀. 一.膨胀 首先需要明确一个概念,膨胀和腐蚀都是针对于图像中较亮的区域而言的,膨胀就是亮的区域变多了,而腐蚀就是暗的区域变多了. 膨胀的功能主要有消除噪声,分割出独立的图像元素,在图像操作的时候,有时候需要对图像中的某些形状进行检测,而这些形状相互连接在一起,不好分开检测,膨胀就能切开这些形状(很小的连接位置),或者图像中有很小块的黑斑,或许是相