一、图像腐蚀 膨胀 细化的基本原理
1.图像细化的基本原理
⑸ 开闭操作 闭操作是先膨胀、后腐蚀处理。
(6) 细化 |
具体详细的图像形态学资料参考:http://wenku.baidu.com/view/1923d18fcc22bcd126ff0ccc.html
二、OpenCv形态学操作相关函数
1、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 模式下需要。
2、Dilate 使用任意结构元素膨胀图像
void cvDilate( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1 );
src
输入图像.
dst
输出图像.
element
用于膨胀的结构元素。若为 NULL, 则使用 3×3 长方形的结构元素
iterations
膨胀的次数
函数 cvDilate 对输入图像使用指定的结构元进行膨胀,该结构决定每个具有最小值象素点的邻域形状:
dst=dilate(src,element): dst(x,y)=max((x',y') in element))src(x+x',y+y')
函数支持(in-place)模式。膨胀可以重复进行 (iterations) 次. 对彩色图像,每个彩色通道单独处理。
3、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')
函数可能是本地操作,不需另外开辟存储空间的意思。腐蚀可以重复进行 (iterations) 次. 对彩色图像,每个彩色通道单独处理。
注:CreateStructuringElementEx 创建结构元素;ReleaseStructuringElement 删除结构元素。
三、OpenCv形态学实例代码:
1、腐蚀、膨胀、开运算、闭运算
内容参考:http://blog.csdn.net/gnuhpc/archive/2009/06/21/4286177.aspx
/*******************************
数学形态运算,最常见的基本运算有七种,
分别为:腐蚀、膨胀、开运算、闭运算、击中、细化和粗化,
它们是全部形态学的基础。
********************************/
#include "cv.h"
#include "highgui.h"
#include <stdlib.h>
#include <stdio.h>
IplImage *src=0;
IplImage *dst=0;
IplConvKernel *element=0;//声明一个结构元素
int element_shape=CV_SHAPE_RECT;//长方形形状的元素
int max_iters=10;
int open_close_pos=0;
int erode_dilate_pos=0;
void OpenClose(int pos)
{
int n=open_close_pos-max_iters;
int an=n>0?n:-n;
element = cvCreateStructuringElementEx(an*2+1, an*2+1,an,an,element_shape,0);//创建结构元素
if (n<0)
{
cvErode(src,dst,element,1);//腐蚀图像
cvDilate(dst,dst,element,1);//膨胀图像
}
else
{
cvDilate(dst,dst,element,1);//膨胀图像
cvErode(src,dst,element,1);//腐蚀图像
}
cvReleaseStructuringElement(&element);
cvShowImage("Open/Close",dst);
}
void ErodeDilate(int pos)
{
int n=erode_dilate_pos-max_iters;
int an=n>0?n:-n;
element = cvCreateStructuringElementEx(an*2+1,an*2+1,an,an,element_shape,0);
if (n<0)
{
cvErode(src,dst,element,1);
}
else
{
cvDilate(src,dst,element,1);
}
cvReleaseStructuringElement(&element);
cvShowImage("Erode/Dilate",dst);
}
int main(int argc,char **argv)
{
char *filename =argc ==2?argv[1]:(char *)"lena.jpg";
if( (src = cvLoadImage(filename,1)) == 0 )
return -1;
dst=cvCloneImage(src);
cvNamedWindow("Open/Close",1);
cvNamedWindow("Erode/Dilate",1);
open_close_pos = erode_dilate_pos = max_iters;
cvCreateTrackbar("iterations","Open/Close",&open_close_pos,max_iters*2+1,OpenClose);
cvCreateTrackbar("iterations","Erode/Dilate",&erode_dilate_pos,max_iters*2+1,ErodeDilate);
for (;;)
{
int c;
OpenClose(open_close_pos);
ErodeDilate(erode_dilate_pos);
c= cvWaitKey(0);
if (c==27)
{
break;
}
switch(c) {
case 'e':
element_shape=CV_SHAPE_ELLIPSE;
break;
case 'r':
element_shape=CV_SHAPE_RECT;
break;
case '/r':
element_shape=(element_shape+1)%3;
break;
default:
break;
}
}
cvReleaseImage(&src);
cvReleaseImage(&dst);
cvDestroyWindow("Open/Close");
cvDestroyWindow("Erode/Dilate");
return 0;
}
/*****************************
腐蚀和膨胀,看上去好像是一对互逆的操作,实际上,这两种操作不具有互逆的关系。
开运算和闭运算正是依据腐蚀和膨胀的不可逆性,演变而来的。
先腐蚀后膨胀的过程就称为开运算。
闭运算是通过对腐蚀和膨胀的另一种不同次序的执行而得到的,
闭运算是先膨胀后腐蚀的过程,其功能是用来填充物体内细小空洞、连接邻近物体、平滑其边界,
同时不明显改变不明显改变其面积。
******************************/
2、opencv实现二值图像细化
内容参考:http://blog.csdn.net/byxdaz/archive/2010/06/02/5642669.aspx