形态学函数cvErode、cvDilate使用说明

来源:互联网 发布:辐射44g内存怎么优化 编辑:程序博客网 时间:2024/05/14 20:17
 

形态学函数cvErode、cvDilate使用说明

形态学操作
HUNNISH 注:
  本翻译是直接根据 OpenCV Beta 4.0 版本的用户手册翻译的,原文件是:<opencv_directory>/doc/ref/opencvref_cv.htm, 可以从 SOURCEFORG 上面的 OpenCV 项目下载,也可以直接从阿须数码 中下载:http://www.assuredigit.com/incoming/sourcecode/opencv/chinese_docs/ref/opencvref_cv.htm。
  翻译中肯定有不少错误,另外也有些术语和原文语义理解不透导致翻译不准确或者错误,也请有心人赐教。翻译这些英文参考手册的目的是想与国内 OPENCV 的爱好者一起提高 OPENCV 在计算机视觉、模式识别和图像处理方面的实际应用水平。
  CreateStructuringElementEx
  创建结构元素
  IplConvKernel* cvCreateStructuringElementEx( int cols, int rows, int anchor_x, int anchor_y,
   int shape, int* values=NULL );
  cols
  结构元素的列数目
  rows
  结构元素的行数目
  anchor_x
  锚点的相对水平偏移量
  anchor_y
  锚点的相对垂直便宜量
  shape
  结构元素的形状,可以是下列值:
  CV_SHAPE_RECT, 长方形元素;
  CV_SHAPE_CROSS, 交错元素 a cross-shaped element;
  CV_SHAPE_ELLIPSE, 椭圆元素;
  CV_SHAPE_CUSTOM, 用户自定义元素。这种情况下参数 values 定义了 mask,即象素的那个邻域必须考虑。
  values
  指向结构元素的指针,它是一个平面数组,表示对元素矩阵逐行扫描。非零值的点表示该点属于该元素。如果点为 NULL,那么所有值都被认为是非零,即元素是一个长方形。该参数仅仅当形状是 CV_SHAPE_CUSTOM 时才予以考虑。
  函数 cv CreateStructuringElementEx 分配和填充结构 IplConvKernel, 它可作为形态操作中的结构元素。
  ReleaseStructuringElement
  删除结构元素
  void cvReleaseStructuringElement( IplConvKernel** element );
  element
  被删除的结构元素的指针
  函数 cvReleaseStructuringElement 释放结构 IplConvKernel 。如果 *element 为 NULL, 则函数不作用。
  Erode
  使用结构元素腐蚀图像
  void cvErode( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1 );
  src
  输入图像.
  dst
  输出图像.
  element
  用于腐蚀的结构元素。若为 NULL, 则使用 3×3 长方形的结构元素
  iterations
  腐蚀的次数
  函数 cvErode 对输入图像使用指定的结构元素进行腐蚀,该结构决定每个具有最小值象素点的邻域形状:
  dst=erode(src,element): dst(x,y)=min((x',y') in element))src(x+x',y+y')
  函数支持(in-place)模式。腐蚀可以重复进行 (iterations) 次. 对彩色图像,每个彩色通道单独处理。
  Dilate
  使用结构元素膨胀图像
  void cvDilate( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1 );
  src
  输入图像.
  dst
  输出图像.
  element
  用于膨胀的结构元素。若为 NULL, 则使用 3×3 长方形的结构元素
  iterations
  膨胀的次数
  函数 cvErode 对输入图像使用指定的结构元素进行腐蚀,该结构决定每个具有最小值象素点的邻域形状:
  函数 cvDilate 对输入图像使用指定的结构元素进行膨胀,该结构决定每个具有最小值象素点的邻域形状:
  dst=dilate(src,element): dst(x,y)=max((x',y') in element))src(x+x',y+y')
  函数支持(in-place)模式。膨胀可以重复进行 (iterations) 次. 对彩色图像,每个彩色通道单独处理。
  MorphologyEx
  高级形态变换
  void cvMorphologyEx( const CvArr* src, CvArr* dst, CvArr* temp,
   IplConvKernel* element, int operation, int iterations=1 );
  src
  输入图像.
  dst
  输出图像.
  temp
  临死图像,某些情况下需要
  element
  结构元素
  operation
  形态操作的类型:
  CV_MOP_OPEN - 开口
  CV_MOP_CLOSE - 闭口
  CV_MOP_GRADIENT - 形态梯度
  CV_MOP_TOPHAT - "顶帽"
  CV_MOP_BLACKHAT - "黑帽"
  iterations
  膨胀和腐蚀次数.
  函数 cvMorphologyEx 在膨胀和腐蚀基本操作的基础上,完成一些高级的形态变换:
  开口:
  dst=open(src,element)=dilate(erode(src,element),element)
  闭口:
  dst=close(src,element)=erode(dilate(src,element),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
  临时图像 temp 在形态梯度以及对“顶帽”和“黑帽”操作时的 in-place 模式下需要。(王朝网络 wangchao.net.cn)

                   创建自己的结构元素对图象进行操作

opencv一些图象处理函数,比如腐蚀cvErode和cvDilate,可以用自己的定制的结构元素进行处理.

 IplConvKernel* kernel = cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_CROSS, NULL); 
 cvErode(cannyImage,cannyImage,0,1);//
 cvReleaseStructuringElement( &kernel );

记得用完需要释放空间.因为在函数cvCreateStructuringElementEx里面Alloc了堆空间.

腐蚀用在消除二值图象不相关的细节,膨胀将断裂的区域桥接起来.

cvCreateStructuringElementEx的第三个参数是表示结构元素的形状,不同的形状处理的结果不一样.腐蚀和膨胀的区域也不一样.

下面是函数的源代码解释了这个结构体

    switch (shape)
    {
    case CV_SHAPE_RECT:
        memset( vals, -1, sizeof( vals[0] ) * cols * rows );//这里就是矩形,每个元素都是-1
        break;
    case CV_SHAPE_CROSS://行偏移的位置为anchorY,列的偏移的位置是anchorX
       memset( vals, 0, sizeof( vals[0] ) * cols * rows );
        for( i = 0; i < cols; i++ )
        {
            vals[i + anchorY * cols] = -1;
        }

        for( i = 0; i < rows; i++ )
        {
            vals[anchorX + i * cols] = -1;
        }
        break;
    case CV_SHAPE_ELLIPSE://椭圆的位置,这个在待分析
      {
            int r = (rows + 1) / 2;
            int c = cols / 2;
            double inv_r2 = 1. / (((double) (r)) * (r));

            memset( vals, 0, sizeof( vals[0] ) * cols * rows );

            for( i = 0; i < r; i++ )
            {
                int y = r - i;
                int dx = cvRound( c * sqrt( ((double)r * r - y * y) * inv_r2 ));
                int x1 = c - dx;
                int x2 = c + dx;

                if( x1 < 0 )
                    x1 = 0;
                if( x2 >= cols )
                    x2 = cols;
                x2 -= x1 - 1;
                memset( vals + i * cols + x1, -1, x2 * sizeof( int ));
                memset( vals + (rows - i - 1) * cols + x1, -1, x2 * sizeof( int ));
            }
        }
        break;
    case CV_SHAPE_CUSTOM://根据values的值填充结构元素
      for( i = 0; i < size; i++ )
        {
            vals[i] = !values || values[i] ? -1 : 0;
        }
        break;
    default:
        cvFree( (void**)&element );
        CV_ERROR_FROM_STATUS( CV_BADFLAG_ERR );
    }

1.引言

形态学运算是针对二值图象依据数学形态学(Mathematical Morphology)的集合论方法发展起来的图象处理方法。数学形态学起源于岩相学对岩石结构的定量描述工作,近年来在数字图象处理和机器视觉领域中得到了广泛的应用,形成了一种独特的数字图象分析方法和理论。

通常形态学图象处理表现为一种邻域运算形式,一种特殊定义的邻域称之为“结构元素”(Structure Element),在每个象素位置上它与二值图象对应的区域进行特定的逻辑运算,逻辑运算的结果为输出图象的相应象素。形态学运算的效果取决于结构元素的大小、内容以及逻辑运算的性质。常见的形态学运算有腐蚀(Erosion)和膨胀(Dilation)。

给定二值图象I(x,y)和作为结构元素的二值模板T(i,j),则典型的腐蚀与膨胀运算可表示成:

腐蚀

膨胀

 

几种简单对称结构元素(圆形、方形、菱形)如下图所示:

2. 基本概念

(1)包含、击中、不击中

按照集合的概念,给定两个集合:对象(Object)X和结构元素(Structure Element)B,它们之间的关系有如图所示的三种情况:

 

(2)平移、对称集

平移

对称集 (将B旋转180度得到)

(3) 腐蚀

腐蚀是一种消除边界点,使边界向内部收缩的过程。可以用来消除小且无意义的物体。一般意义的腐蚀概念定义为


 

也就是说,由B对X腐蚀所产生的二值图象E是满足以下条件的点(x,y)的集合:如果B的原点平移到点(x,y),那么B将完全包含于X中。

(4)膨胀

膨胀是将与物体接触的所有背景点合并到该物体中,使边界向外部扩张的过程。可以用来填补物体中的空洞。一般意义的膨胀概念定义为


 

也就是说,由B对X膨胀所产生的二值图象D是满足以下条件的点(x,y)的集合:如果B的原点平移到点(x,y),那么它与X的交集非空。

 

性质:对偶关系

例如:

 

 

另外,腐蚀和膨胀都可以用平移来说明:


 

例如,在下图中利用圆形结构元素做膨胀运算,填补“细缝”。

(图片来源:艾海舟,王栓,何克忠,基于差分图象的人脸检测,中国图象图形学报,1998; 3(12): 987-992.)

3. 开运算和闭运算

(1)开运算

先腐蚀后膨胀的过程称为开运算。用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。


 

(2)闭运算

先膨胀后腐蚀的过程称为闭运算。用来填充物体内细小空洞、连接邻近物体、平滑其边界的同时并不明显改变其面积。


 

通常,由于噪声的影响,图象在阈值化后所得到边界往往是很不平滑的,物体区域具有一些噪声孔,背景区域上散布着一些小的噪声物体。连续的开和闭运算可以有效地改善这种情况。有时需要经过多次腐蚀之后再加上相同次数的膨胀,才可以产生比较好的效果。

例如:开运算,B1作用结果:去掉小刺,但未去掉小桥;B2作用结果:有位移。

 

闭运算,B1作用结果:去掉小刺,但未去掉小桥;B2作用结果:去掉小刺,和小桥。

 

4. 击中击不中变换HMT(Hit-Miss Transform)

将形态学运算推广到更为一般的情况,实际上就演变为条件严格的模板匹配。这时结构元素不仅含有物体点,而且还含有背景点,只有当结构元素与所对应的区域完全符合时才作为结果输出到输出图象。

模板T由两部分组成(T1,T2), T1物体点,T2背景点,HMT定义为

例如,在下图中,对于三个不同的T模板,在X中标出了符合条件的位置。

 

性质:(1)时,

(2)

4.1细化和粗化

(1)细化(Thin)

细化可以通过逐步去掉满足匹配条件的点的方法来实现,每步运算可表示成:

系统地细化需要考虑一系列的模板,如其中 是 旋转的结果(90º ,180º ,270º )共8种情况。

例如,可用于细化的结构元素有

          

问题:用 , 是否包含所有可删除的情况?是否包含端点?

具体的细化算法参见第七章(..\chapter07\script07_ahz.htm)。

(2)粗化(Thick)

用点集合 , 时,

故要选择合适的结构元素,如

对偶性: (验证一下)

其中,当 时,

 

5. 边界和骨架(Boundary and Skeleton)

边界运算可以用:

抽骨架(Skeletonization)(骨架也称为中轴medial axis)与细化不同主要在于中轴骨架在拐角处延伸到了边界,而细化则不是。抽骨架的一种方法是:

其中

用不同大小的结构元素nG逐步对X腐蚀,直到 ,每次腐蚀得到宽度和nG成正比的区域段的骨架。

 

以上方法存在一些问题,如有时骨架不连通了,而原区域是连通。一种改进的方法是采用全方形的结构元素

        

演示:..\SourceProgramCodes\chapter9\武勃981403\Debug\ViewDIB.exe

  Binary Sobel Edge

 Dilation

 Erosion

 Open

 Close

 Thinning by Structure Elemnets of T and L shapes

 

相关的网上资料:Morphology-based Operations.htm(..\..\download_IPCVPR\IPFundamentals\Morphology-based Operations.htm)

致谢:本章的形态学运算示意图取自朱志刚博士的讲义:朱志刚,数字图象处理,1998年6月,pp.94-102。祥见其讲义:3.6 形态学运算(..\Readings\chapter08\6morph.doc)

推荐参考资料:Edward Dougherty (ed.), Mathematical morphology in image processing, M. Dekker, New York, 1993.

 

作业

  1. 在二值化程序基础上,编制基本的形态学运算(腐蚀和膨胀、开闭)程序,针对输入的任意图象选择不同的阈值做二值化,再做形态学处理,通过交互输入不同类型的结构元素观察效果。
  2. 编制抽取中轴的程序,通过用画板等方式生成的各种类型的二值图象观察效果。

返回主目录返回本章目录

清华大学计算机系 艾海舟

最近修改时间:2001年7月18日

文献来源:http://www.wangchao.net.cn/bbsdetail_41463.html

          http://calendar.roarsoft.net/a/201107/14740.html        

        http://media.cs.tsinghua.edu.cn/~ahz/digitalimageprocess/chapter08/chapt08_ahz.htm

原创粉丝点击