Erode腐蚀, Dilate膨胀,这两个形态学函数总是成对出现,前者可以消除较小的点如噪音,后者可以使不连通的图像合并成块。
void cvErode( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1 );
void cvDilate( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1 );
这两个函数的参数相同,是一对“相反”的函数(这里的相反并不是指后一个函数可以将前一个函数处理的图像恢复,而是一个缩小图像团块,一个放大图像的团块)
src 输入图像.
dst 输出图像.
element 用于膨胀的结构元素。若为 NULL, 则使用 3×3 长方形的结构元素
iterations 膨胀的次数。 膨胀可以重复进行 (iterations) 次. 对彩色图像,每个彩色通道单独处理。
下面的程序将演示这两个函数,腐蚀和膨胀的过程
#include<iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp> #include "cv.h"
#include "cxcore.h"
#include "highgui.h"
int main(int argc, char** argv)
{if (argc<2)return 0;//检查输入参数int a = 1;int eIter = 1, dIter = 1, exitFlag = 1;IplImage *image, *image1, *image2;image = cvLoadImage(argv[1]);image1 = cvCreateImage(cvSize(image->width, image->height), 8, 1);//创建首地址并分配存储空间image2 = cvCreateImage(cvSize(image->width, image->height), 8, 1);cvCvtColor(image, image1, CV_RGB2GRAY);//实现RGB颜色向HSV,HSI等颜色空间的转换. 参数CV_RGB2GRAY是RGB到gray(灰度图)c参数 CV_GRAY2RGB是gray到RGB.cvCvtColor(image, image2, CV_RGB2GRAY);cvNamedWindow("image", 1);cvShowImage("image", image);/* 对话框未使用cvNamedWindow("Select", 1);cvCreateTrackbar("eIterations", "Select", &eIter, 20, 0); //参数1滑块名称 参数2显示窗口 参数3 OPENCV将当前滑块位置值传给指针指向的整数 参数4滑块调整范围最大值 参数5指向回调函数的指针,当滑动条被拖动时,函数自动调用 cvCreateTrackbar("dIterations", "Select", &dIter, 20, 0);//参数1滑块名称 参数2显示窗口 参数3 OPENCV将当前滑块位置值传给指针指向的整数 参数4滑块调整范围最大值 参数5指向回调函数的指针,当滑动条被拖动时,函数自动调用*/cvNamedWindow("Erode_fushi", 1);cvNamedWindow("Dilate_pengzhang", 1);cvShowImage("Erode_fushi", image1);cvShowImage("Dilate_pengzhang", image2);cvWaitKey(0);while (1){cvErode(image1, image1, 0, 1); /*cvErode腐蚀,消除细小物质src 输入图像.dst 输出图像.element 用于腐蚀的结构元素。若为 NULL, 则使用 3×3 长方形的结构元素iterations 腐蚀的次数. 腐蚀可以重复进行(iterations) 次.对彩色图像,每个彩色通道单独处理。*/cvShowImage("Erode_fushi", image1);std::cout << "Erode_fushi" << std::endl;a = cvWaitKey(0);if ((char)a == 'q')break;}cvCopy(image1, image2);a = 1;while (1){cvDilate(image2, image2, 0, 1); //膨胀,填充物体内细小物质/*cvDilate膨胀,消除细小物质src 输入图像.dst 输出图像.element 用于膨胀的结构元素。若为 NULL, 则使用 3×3 长方形的结构元素iterations 膨胀的次数. 膨胀可以重复进行(iterations) 次.对彩色图像,每个彩色通道单独处理。*/cvShowImage("Dilate_pengzhang", image2);std::cout << "Dilate_pengzhang" << std::endl;a = cvWaitKey(0);if ((char)a == 'q')break;}//释放窗口资源return 0;
}
原图:
腐蚀:
膨胀:
一
二
(1)二值形态学
(2)灰度数学形态学
对灰度图像的膨胀(或腐蚀)操作有两类效果:
(1)如果结构元素的值都为正的,则输出图像会比输入图像亮(或暗);
(2)根据输入图像中暗(或亮)细节的灰度值以及它们的形状相对于结构元素的关系,它们在运算中或被消减或被除掉。灰度数学形态学中开启和闭合运算的定义与在二值数学形态学中的定义一致。用b对f进行开启和闭合运算的定义为:
(3)模糊数学形态学
其中,x,y∈Z2代表空间坐标,ua,ub分别代表图像和结构元素的隶属函数。从(7),(8)式的结果可知,经模糊形态腐蚀膨胀运算后的隶属函数均落在[0,1]的区间内。模糊形态学是传统数学形态学从二值逻辑向模糊逻辑的推广,与传统数学形态学有相似的计算结果和相似的代数特性。模糊形态学重点研究n维空间目标物体的形状特征和形态变换,主要应用于图像处理领域,如模糊增强、模糊边缘检测、模糊分割等。
三
近年来,数学形态学在图像处理方面得到了日益广泛的应用。下面主要就数学形态学在边缘检测、图像分割、图像细化以及噪声滤除等方面的应用做简要介绍。
(1)
边缘检测是大多数图像处理必不可少的一步,提供了物体形状的重要信息。对于二值图像,边缘检测是求一个集合A的边界,记为B(A):
对于灰度图像,边缘检测是求一幅图像的形态学梯度,记为g:
数学形态学运算用于边缘检测,存在着结构元素单一的问题。它对与结构元素同方向的边缘敏感,而与其不同方向的边缘(或噪声)会被平滑掉,即边缘的方向可以由结构元素的形状确定。但如果采用对称的结构元素,又会减弱对图像边缘的方向敏感性。所以在边缘检测中,可以考虑用多方位的形态结构元素,运用不同的结构元素的逻辑组合检测出不同方向的边缘。
梁勇等人构造了8个方向的多方位形态学结构元素,应用基本形态运算,得到8个方向的边缘检测结果,再把这些结果进行归一化运算、加权求和,得到最终的图像边缘。该算法在保持图像细节特征和平滑边缘等方面,取得了较好的效果。
(2)
基于数学形态学的图像分割算法是利用数学形态学变换,把复杂目标X分割成一系列互不相交的简单子集X1,X2,…,XN,即:
对目标X的分割过程可按下面的方法完成:首先求出X的最大内接“圆”X1,然后将X1从X中减去,再求X-X1的最大内接“圆”X2,…,依此类推,直到最后得到的集合为空集为止。下面以二值图像为例,介绍用数学形态学方法求解子集X1,X2,…,XN的过程。
设B为结构元素,B可以是圆、三角形、正方形等简单的几何基元,那么“简单”形状集合Xi可以用下面的公式来定义:
式中ni为一整数,用上式定义Xi分割目标,有时会产生分割过程不唯一的现象。为此可采用下面公式来定义简单集合Xi:
其中Li为一个点或一条线,当Li为点时,则与(12)式定义等价。(13)式定义的简单形状Xi可由niB沿线Li移动而产生。即将“产生器”niB的中心沿“脊骨”Li移动产生。如果niB为圆,则得到的Xi称Blum带。它具有一些特殊的性质,如Xi的边界是光滑的,Xi的最大圆与其边界相切,Xi的脊骨与产生器都是唯一的等等。
有了简单形状集合Xi的定义,则目标X可按下面方法分割。首先按式(14)求出X的最大内切结构元素Xi:
数学形态学用于图像分割的缺点是对边界噪声敏感。为了改善这一问题,刘志敏等人提出了基于图像最大内切圆的数学形态学形状描述图像分割算法和基于目标最小闭包结构元素的数学形态学形状描述图像分割算法,并使用该算法对二值图像进行了分割,取得了较好的效果。邓世伟等人提出一种基于数学形态学的深度图像分割算法。作者首先利用形态学算子获得分别含有阶跃边缘与屋脊边缘的凸脊和凹谷图像,然后利用控制区域生长过程得到最终的分割结果。与传统方法相比,该方法速度快,抗噪性能好。
(3)
形态骨架描述了物体的形状和方向信息。它具有平移不变性、逆扩张性和等幂性等性质,是一种有效的形状描述方法。二值图像A的形态骨架可以通过选定合适的结构元素B,对A进行连续腐蚀和开启运算来求取,设S(A)代表A的骨架,定义为:
蒋刚毅等人运用数学形态学方法,对交通标志的内核形状提取形态骨架函数,将其作为用于模式匹配的形状特征。A的形态骨架函数SKF(A)表示为:
SKF(X)中值较大的点对应大的n,并代表了形态骨架的主要成分,即表达了形状的主体结构;而SKF(X)中值较小的点对应小的n,是形态骨架的细节成分,与形状的边缘信息相联系。
形态骨架函数完整简洁地表达了形态骨架的所有信息,因此,根据形态骨架函数的模式匹配能够实现对不同形状物体的识别。算法具有位移不变性,因而使识别更具稳健性。
(4)
对图像中的噪声进行滤除是图像预处理中不可缺少的操作。将开启和闭合运算结合起来可构成形态学噪声滤除器。
对于二值图像,噪声表现为目标周围的噪声块和目标内部的噪声孔。用结构元素B对集合A进行开启操作,就可以将目标周围的噪声块消除掉;用B对A进行闭合操作,则可以将目标内部的噪声孔消除掉。该方法中,对结构元素的选取相当重要,它应当比所有的噪声孔和噪声块都要大。
对于灰度图像,滤除噪声就是进行形态学平滑。实际中常用开启运算消除与结构元素相比尺寸较小的亮细节,而保持图像整体灰度值和大的亮区域基本不变;用闭合运算消除与结构元素相比尺寸较小的暗细节,而保持图像整体灰度值和大的暗区域基本不变。将这两种操作综合起来可达到滤除亮区和暗区中各类噪声的效果。同样的,结构元素的选取也是个重要问题。
四
分析表明,各种数学形态学算法的应用可分解为形态学运算和结构元素选择两个基本问题,形态学运算的规则已由定义确定,于是形态学算法的性能就取决于结构元素的选择,亦即结构元素决定着形态学算法的目的和性能。因此如何自适应地优化确定结构元素,就成为形态学领域中人们长期关注的研究热点和技术难点。目前较多采用多个结构元素对图像进行处理的方法。
(1)
在许多形态学应用中,往往只采用一个结构元素,这通常不能产生满意的结果。在模式识别中,如果要提取某个特定的模式,只采用一个结构元素,那么,只有与结构元素形状、大小完全相同的模式才能被提取,而与此结构元素表示的模式即使有微小差别的其他模式的信息都不能获取。
解决此问题的一个有效方法之一就是将形态学运算与集合运算结合起来,同时采用多个结构元素,分别对图像进行运算,然后将运算后的图像合并起来,即多结构元素形态学运算。
(2)
遗传算法的思想来源于自然界物竞天择、优胜劣汰、适者生存的演化规律和生物进化原理,并引用随机统计理论而形成,具有高效并行全局优化搜索能力,能有效地解决机器学习中参数的复杂优化和组合优化等难题。
近年来不少国外学者已进行了这方面的探索与研究,Ehrgardt设计了形态滤波的遗传算法,用于二值图像的去噪和根据二值纹理特性消除预定目标;Huttumen利用遗传算法构造了软式形态滤波器及其参数优化的设计方法,以实现灰度图像的降噪功能。余农、李予蜀等人用遗传算法在自然景象的目标检测与提取方面进行了研究,通过自适应优化训练使结构元素具有图像目标的形态结构特征,从而赋予结构元素特定的知识,使形态滤波过程融入特有的智能,以实现对复杂变化的图像具有良好的滤波性能和稳健的适应能力。其实质是解决滤波器设计中知识获取和知识精炼的机器学习问题。
五
数学形态学是一门建立在集论基础之上的学科,是几何形状分析和描述的有力工具。近年来,数学形态学在数字图像处理、计算机视觉与模式识别等领域中得到了越来越广泛的应用,渐渐形成了一种新的数字图像分析方法和理论,引起了国内外相关领域研究人员的广泛关注。目前,数学形态学存在的问题及研究方向主要集中在以下几个方面:
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
六
数学形态学对图像的处理具有直观上的简明性和数学上的严谨性,在定量描述图像的形态特征上具有独特的优势,为基于形状细节进行图像处理提供了强有力的手段。建立在集合理论基础上的数学形态学,主要通过选择相应的结构元素采用膨胀、腐蚀、开启、闭合#种基本运算的组合来处理图像。数学形态学在图像处理中的应用广泛,有许多实用的算法,但在每种算法中结构元素的选取都是一个重要的问题。
用3x3的结构元素,扫描图像的每一个像素,用结构元素与其覆盖的二值图像做“与”操作:如果都为1,结果图像的该像素为1。否则为0。 结果:使二值图像减小一圈 定义:E = B S = { x,y | SxyB}膨胀的算法: 用3x3的结构元素,扫描图像的每一个像素,用结构元素与其覆盖的二值图像做“与”操作:如果都为0,结果图像的该像素为0。否则为1 结果:使二值图像扩大一圈 定义:E = B S = { x,y | Sxy∩B ≠Ф}代码: VC++code
#include
#include
#include
#include
#include
unsigned char **get_matrix_space(int m,intn)
{
int i;
unsigned char **a;
a=(unsigned char **)calloc(m,sizeof(unsigned char*));
for(i=0;ireturn a;
}
main(){
FILE *fs,*fd;
unsigned charc1,c2,**ps,**pd,**get_matrix_space(int,int);
int width,height,L,i,j,l,m,match;
fscanf(fs,"%c%c\n%d%d\n%d\n",&c1,&c2,&width,&height,&L);
ps=get_matrix_space(height,width);
pd=get_matrix_space(height,width);
for(i=0;i
}
///
match = 1;
for(i=0;i
}
//
fprintf(fd,"%c%c\n%d%d\n%d\n",'P','5',width,height,L);
for(i=0;i
}
}
#include
#include
#include
#include
#include
unsigned char **get_matrix_space(int m,intn)
{
int i;
unsigned char **a;
a=(unsigned char **)calloc(m,sizeof(unsigned char*));
for(i=0;ireturn a;
}
main(){
FILE *fs,*fd;
unsigned charc1,c2,**ps,**pd,**v,**get_matrix_space(int,int);
intwidth,height,L,i,j,l,m,windowSize,match;
fscanf(fs,"%c%c\n%d%d\n%d\n",&c1,&c2,&width,&height,&L);
ps=get_matrix_space(height,width);
pd=get_matrix_space(height,width);
for(i=0;i
}
match = 0;
//
//用2x2方块作为膨胀的结构元素。
for(i=0;i
}
//
fprintf(fd,"%c%c\n%d%d\n%d\n",'P','5',width,height,L);
for(i=0;i
}
}
一般先将处理图像转为整型或逻辑型再处理即可。