一、图像腐蚀 膨胀 细化的基本原理
膨胀和腐蚀这两种操作是形态学处理的基础,许多形态学算法都是以这两种运算为基础的。
1 膨胀
是以得到B的相对与它自身原点的映像并且由z对映像进行移位为基础的。A被B膨胀是所有位移z的集合,这样,和A至少有一个元素是重叠的。我们可以把上式改写为:
结构元素B可以看作一个卷积模板,区别在于膨胀是以集合运算为基础的,卷积是以算术运算为基础的,但两者的处理过程是相似的。
⑴ 用结构元素B,扫描图像A的每一个像素
⑵ 用结构元素与其覆盖的二值图像做“与”操作
⑶ 如果都为0,结果图像的该像素为0。否则为1
膨胀
2 腐蚀
对Z中的集合A和B,B对A进行腐蚀的整个过程如下:
⑴ 用结构元素B,扫描图像A的每一个像素
⑵ 用结构元素与其覆盖的二值图像做“与”操作
⑶ 如果都为1,结果图像的该像素为1。否则为0
腐蚀处理的结果是使原来的二值图像减小一圈。
腐蚀通常用来消除斑点噪声他能将图像中的斑点消除 且确保较大区域的存在
3 开闭操作
开操作是先腐蚀、后膨胀处理。
闭操作是先膨胀、后腐蚀处理。
开运算消除了高于区域临近点的孤立点,而比运算消除了低于区域临近点的孤立点
4 细化
图像细化一般作为一种图像预处理技术出现,目的是提取源图像的骨架,即是将原图像中线条宽度大于1个像素的线条细化成只有一个像素宽,形成“骨架”,形成骨架后能比较容易的分析图像,如提取图像的特征。
细化基本思想是“层层剥夺”,即从线条边缘开始一层一层向里剥夺,直到线条剩下一个像素的为止。图像细化大大地压缩了原始图像地数据量,并保持其形状的基本拓扑结构不变,从而为文字识别中的特征抽取等应用奠定了基础。细化算法应满足以下条件:
① 将条形区域变成一条薄线;
② 薄线应位与原条形区域的中心;
③ 薄线应保持原图像的拓扑特性。
细化分成串行细化和并行细化,串行细化即是一边检测满足细化条件的点,一边删除细化点;并行细化即是检测细化点的时候不进行点的删除只进行标记,而在检测完整幅图像后一次性去除要细化的点。
常用的图像细化算法有hilditch算法,pavlidis算法和rosenfeld算法等。
注:进行细化算法前要先对图像进行二值化,即图像中只包含“黑”和“白”两种颜色。
二、OpenCv形态学操作相关函数
1、Dilate 使用任意结构元素膨胀图像
void cvDilate
(
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) 次. 对彩色图像,每个彩色通道单独处理。
2、Erode 使用任意结构元素腐蚀图像
void cvErode(
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 删除结构元素。
3、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 模式下需要。
###########################################################################
#include "cv.h"
#include "highgui.h"
int main()
{
IplImage *src=cvLoadImage("C:\\111.jpg");
if(src == NULL)
{
printf("img load failed!\n");
return 0;
}
IplImage *dst=cvCreateImage(
cvGetSize(src),
IPL_DEPTH_8U,
3
);
IplConvKernel *element=NULL;
cvErode(src,dst,element,1);//腐蚀图像
cvDilate(dst,dst,NULL,1);//膨胀图像
cvNamedWindow("example1",CV_WINDOW_AUTOSIZE);
cvShowImage("example1",dst);
cvWaitKey(0);
cvReleaseImage(&src);
cvReleaseImage(&dst);
cvDestroyAllWindows();
}
#######################################################
#include "cv.h"
#include "highgui.h"
int main ()
{
IplImage *src =cvLoadImage("c:\\111.jpg");
cvNamedWindow("sourceImage");
cvShowImage("sourceImage",src);
cvNamedWindow("open");
cvNamedWindow("close");
cvNamedWindow("gradient");
cvNamedWindow("topHat");
cvNamedWindow("blackHat");
IplImage *temp = cvCreateImage(cvGetSize(src),8,3);
IplImage *img = cvCreateImage(cvGetSize(src),8,3);
//开运算
cvMorphologyEx(
src,
img,
temp,
NULL, //default 3*3
CV_MOP_OPEN,
4);
cvShowImage("open", img);
//闭运算
cvMorphologyEx(
src,
img,
temp,
NULL, //default 3*3
CV_MOP_CLOSE,
4);
cvShowImage("close", img);
//形态梯度
cvMorphologyEx(
src,
img,
temp,
NULL, //default 3*3
CV_MOP_GRADIENT,
3
);
cvShowImage("topHat", img);
//cvWaitKey(0);
//“黑帽”
cvMorphologyEx(
src,
img,
temp,
NULL, //default 3*3
CV_MOP_BLACKHAT,
3);
cvShowImage("blackHat", img);
cvWaitKey(0);
cvReleaseImage(&temp);
cvReleaseImage(&src);
cvReleaseImage(&img);
cvDestroyAllWindows();
return 0;
}