赞
踩
形态学(morphology)常应用在生物学中,研究动植物的形态和结构;
图像形态学即数学形态学(Mathematical morphology)是一门建立在格伦和拓扑学基础上的图像分析学科,是数学形态学图像处理的基本理论;
常见图像形态学运算:腐蚀、膨胀、开运算、闭运算、骨架抽取、极线腐蚀、击中击不中变换、Top-hat变换、颗粒分析、流域变换、形态学梯度等;
膨胀、腐蚀、开、闭运算是数学形态学最基本的变换。
- 膨胀:把二值图像各1像素连接成分的边界扩大一层(填充边缘或0像素内部的孔);
膨胀操作会扩大(粗化)图像中物体的轮廓,可以用来弥补(填充)物体间的孔洞,强化离散点,代价是导致物体的面积比原来的面积要大。
- 腐蚀:把二值图像各1像素连接成分的边界点去掉从而缩小一层(可提取骨干信息,去掉毛刺,去掉孤立的0像素);
腐蚀操作会收缩(细化)图像中物体的轮廓,可以用来断开(分离)物体间的连接,消除离散点,代价是导致物体的面积比原来的面积要小。
- 开:先腐蚀再膨胀,可以去掉目标外的孤立点
- 闭:先膨胀再腐蚀,可以去掉目标内的孔。
数学形态学中二值图像的形态变换是一种针对集合的处理过程。
其形态算子的实质是表达物体或形状的集合与结构元素间的相互作用,结构元素的形状就决定了这种运算所提取的信号的形状信息。形态学图像处理是在图像中移动一个结构元素,然后将结构元素与下面的二值图像进行交、并等集合运算。
基本的形态运算是腐蚀和膨胀。
在形态学中,结构元素是最重要最基本的概念。
结构元素在形态变换中的作用相当于信号处理中的“滤波窗口”。用B(x)——代表结构元素,对工作空间E中的每一点x,腐蚀和膨胀的定义为:
- 用B(x)对E进行腐蚀的结果就是把结构元素B平移后使B包含于E的所有点构成的集合。
- 用B(x)对E进行膨胀的结果就是把结构元素B平移后使B与E的交集非空的点构成的集合。
- 先腐蚀后膨胀的过程称为开运算。它具有消除细小物体,在纤细处分离物体和平滑较大物体边界的作用。
- 先膨胀后腐蚀的过程称为闭运算。它具有填充物体内细小空洞,连接邻近物体和平滑边界的作用。
卷积核沿着图像滑动,如果与卷积核对应的原图像的所有像素值都为1,那么中心元素就保持原来的像素值,否则为0。
根据卷积核的大小靠近前景的所有像素都会被腐蚀掉(变为0),所以前景物体会变小,整幅图像的白色区域会减少。这对于去除白噪声很有用。
原理
腐蚀:局部最小值(与膨胀相反);
①定义一个卷积核B
核可以是任何的形状和大小,且拥有一个单独定义出来的参考点-锚点(anchorpoint);通常核为带参考点的正方形或者圆盘,可将核称为模板或掩膜;
②将核B与图像A进行卷积,计算核B覆盖区域的像素点最小值;
1.用结构元素,扫描图像的每一个像素
2.用结构元素与其覆盖的二值图像做“与”操作
3.如果都为1,结果图像的该像素为1。否则为0
③将这个最小值赋值给参考点指定的像素
因此,图像中的高亮区域逐渐减小。
说明
通过特定的结构元素腐蚀图像。
该函数使用指定的结构元素腐蚀源图像,该结构化元素确定在其上采用最小值的像素邻域的形状:
可以进行多次(迭代)腐蚀。在多通道图像的情况下,每个通道都是独立处理的。
声明
void erode(
InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor = Point(-1,-1),
int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue()
);
参数
src | 输入图像,通道数可以是任意的,但深度应该为CV_8U,CV_16U,CV_16S,CV_32F或者CV_64F之一。 |
---|---|
dst | 输出与src大小和类型相同的图像。 |
kernel | 用于侵蚀的结构元素;如果为element=Mat(),3 x 3则使用矩形结构元素。可以使用getStructuringElement创建内核 |
anchor | 锚在元素内的位置;默认值(-1,-1)表示锚点位于元素中心。 |
iterations | 施加腐蚀的次数。 |
borderType | |
borderValue | 边界不变时候的边界值。 |
应用
void erodeMethod(Mat &src) {
imshow("src", src);
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
erode(src, src, kernel, Point(-1, -1));
imshow("erode", src);
}
与腐蚀相反,与卷积核对应的原图像的像素值中只要有一个是 1,中心元 素的像素值就是 1。所以这个操作会增加图像中的白色区域(前景)。一般在去噪声时先用腐蚀再用膨胀
原理
求局部最大值;
①定义一个卷积核B
核可以是任何的形状和大小,且拥有一个单独定义出来的参考点-锚点(anchorpoint);
通常和为带参考点的正方形或者圆盘,可将核称为模板或掩膜;
②将核B与图像A进行卷积,计算核B覆盖区域的像素点最大值;
1.用结构元素,扫描图像的每一个像素
2.用结构元素与其覆盖的二值图像做“与”操作
3.如果都为0,结果图像的该像素为0。否则为1
③将这个最大值赋值给参考点指定的像素
因此,图像中的高亮区域逐渐增长。
说明
通过使用特定的结构元素来扩展运行长度编码的二进制图像。
该函数使用指定的结构元素对源图像进行扩展,该结构元素确定在其上取最大值的像素邻域的形状:
dst
(
x
,
y
)
=
max
(
x
′
,
y
′
)
:
element
(
x
′
,
y
′
)
≠
0
src
(
x
+
x
′
,
y
+
y
′
)
\texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')
dst(x,y)=(x′,y′):element(x′,y′)=0maxsrc(x+x′,y+y′)
可以进行几次(迭代)扩张。在多通道图像的情况下,每个通道都是独立处理的。
声明
void dilate(
InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor = Point(-1,-1),
int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue()
);
参数
src | 输入图像,通道可以任意,但深度应该为CV_8U,CV_16U,CV_16S,CV_32F或者CV_64F之一。 |
---|---|
dst | 输出与src大小和类型相同的图像。 |
kernel | 用于扩张的结构元素;如果elemenat = Mat(),则使用3 x 3的矩形结构元素。可以使用getStructuringElement创建内核。 |
anchor | 锚在元素内的位置;默认值(-1,-1)表示锚点位于元素中心。 |
iteration | 扩张的次数。 |
borderType | 参见BorderType。 |
borderValue | 边界不变时的边界值。 |
应用
void dilateMethod(Mat &src) {
imshow("src", src);
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
dilate(src, src, kernel, Point(-1, -1));
imshow("dilate", src);
}
膨胀和腐蚀的主要用途:
- 消除噪声;
- 分割出独立的图像元素,在图像中连接相邻的元素;
- 寻找图像中明显的极大值或极小值区;
- 求出图像的梯度;
腐蚀和膨胀是对像素值大的部分而言的,即高亮白部分而不是黑色部分;
膨胀是图像中的高亮部分进行膨胀,领域扩张,效果图拥有比原图更大的高亮区域;
腐蚀是图像中的高亮部分被腐蚀掉,领域缩减,效果图拥有比原图更小的高亮区域;
利用morphologyEx这个函数可以方便的对图像进行一系列的膨胀腐蚀组合。
说明
执行高级形态转换。
函数cv :: morphologyEx可以使用侵蚀和膨胀作为基本操作来执行高级形态转换。
在多通道图像的情况下,每个通道都是独立处理的。
声明
void morphologyEx(
InputArray src,
OutputArray dst,
int op,
InputArray kernel,
Point anchor = Point(-1,-1),
int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue()
);
参数
src | 源图像。通道数可以是任意的。深度应为CV_8U,CV_16U,CV_16S,CV_32F或CV_64F之一。 |
---|---|
dst | 与源图像大小和类型相同的目标图像。 |
p | 形态学操作的类型,请参见MorphTypes |
kernel | 结构元素。可以使用getStructuringElement创建它。 |
anchor | 内核的锚位置。负值表示锚点位于内核中心。 |
iterations | 施加腐蚀和膨胀的次数。 |
borderType | 边缘类型,默认为BORDER_CONSTANT。请参见BorderTypes。 |
borderValue | 边界不变时的边界值。默认值具有特殊含义。 |
参数op:操作的类型。
enum MorphTypes{ MORPH_ERODE = 0, //腐蚀 MORPH_DILATE = 1, //膨胀 MORPH_OPEN = 2, //开操作 MORPH_CLOSE = 3, //闭操作 MORPH_GRADIENT = 4, //梯度操作 MORPH_TOPHAT = 5, //顶帽操作 MORPH_BLACKHAT = 6, //黑帽操作 MORPH_HITMISS = 7 };
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
迭代次数是将应用腐蚀或膨胀操作的次数。例如,具有两个迭代的打开操作(MORPH_OPEN)等效于依次应用:腐蚀->腐蚀->膨胀->膨胀(而不是腐蚀->膨胀->腐蚀->膨胀)。
①MORPH_ERODE(腐蚀)
与erode函数的腐蚀效果相同。
②MORPH_DILATE(膨胀)
与dilate函数的膨胀效果相同。
③MORPH_OPEN(开)
数学公式:
d s t = o p e n ( s r c , e l e m e m t ) = d i l a t e ( e r o d e ( s r c , e l e m e n t ) ) dst=open(src,elememt)=dilate(erode(src,element)) dst=open(src,elememt)=dilate(erode(src,element))
void openMethod(Mat &src) { Mat dst; Mat kernel = getStructuringElement(MORPH_RECT,Size(5,5)); morphologyEx(src,dst,MORPH_OPEN , kernel); imshow("dst", dst); } int main() { Mat src = imread("D:/test/weixin.jpg"); if (src.empty()) { cout << "图片打开失败!" << endl; } imshow("src", src); openMethod(src); waitKey(0); return 0; }
④ MORPH_CLOSE(闭)
数学公式
d s t = c l o s e ( s r c , e l e m e n t ) = e r o d e ( d i l a t e ( s r c , e l e m e n t ) ) dst=close(src,element)=erode(dilate(src,element)) dst=close(src,element)=erode(dilate(src,element))
void closeMethod(Mat& src) {
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
morphologyEx(src, src, MORPH_CLOSE, kernel);
imshow("close", src);
⑤ MORPH_GRADIENT(梯度)
数学公式
d s t = m o r p h _ g r a d i e n t ( s r c , e l e m e n t ) = d i l a t e ( s r c , e l e m e m t ) − e r o d e ( s r c , e l e m e n t ) dst=morph\_gradient(src,element)=dilate(src,elememt)-erode(src,element) dst=morph_gradient(src,element)=dilate(src,elememt)−erode(src,element)
void gradientMethod(Mat& src) {
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
morphologyEx(src, src, MORPH_GRADIENT, kernel);
imshow("gradient", src);
}
⑥MPRPH_TOPHAT(顶帽)
功能
因为开运算带来的结果是放大了裂缝或者局部低亮度的区域,因此,从原图中减去开运算后的图,得到的效果图突出了比原型轮廓周围的区域更明亮的区域。且这一操作和选择的核的大小有关。
顶帽运算往往用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的时候,可以用顶帽运算进行背景提取。
数学公式
为原图像与上文刚介绍的“开运算”的结果图之差,表达式如下:
d s t = t o p h a t ( s r c , e l e m e n t ) = s r c − o p e n ( s r c , e l e m e n t ) dst=tophat(src,element)=src-open(src,element) dst=tophat(src,element)=src−open(src,element)
应用
void tophatMethod(Mat& src) {
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
morphologyEx(src, src, MORPH_TOPHAT, kernel);
imshow("gradient", src);
}
⑦MORPH_BLACKHAT(黑帽)
功能
黑帽(Black Hat)运算为”闭运算“的结果图与原图像之差。
黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关。
所以,黑帽运算用来分离比邻近点暗一些的斑块。
数学表达式:
d s t = b l a c k h a t ( s r c , e l e m e n t ) = c l o s e ( s r c , e l e m e n t ) − s r c dst=blackhat(src,element)=close(src,element)-src dst=blackhat(src,element)=close(src,element)−src
应用
void blackhatMethod(Mat& src) {
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
morphologyEx(src, src, MORPH_BLACKHAT, kernel);
imshow("gradient", src);
}
Mat src,dst1, dst2,dst3,dst4,dst5,dst6,dst7; int step_size = 3; int max_size = 21; void my_dilate(int ,void*) { int s = step_size * 2 + 1; Mat structingElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1)); dilate(src, dst1, structingElement); imshow("dilate", dst1); return; } void my_erode(int, void*) { int s = step_size * 2 + 1; Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s)); erode(src, dst2, kernel); imshow("erode", dst2); return; } void my_open(int, void*) { int s = step_size * 2 + 1; Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s)); morphologyEx(src, dst3, MORPH_OPEN, kernel); imshow("open", dst3); } void my_close(int, void*) { int s = step_size * 2 + 1; Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s)); morphologyEx(src, dst4, MORPH_CLOSE, kernel); imshow("close", dst4); } void my_gradient(int, void*) { int s = step_size * 2 + 1; Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s)); morphologyEx(src, dst5, MORPH_GRADIENT, kernel); imshow("gradient", dst5); } void my_tophat(int, void*) { int s = step_size * 2 + 1; Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s)); morphologyEx(src, dst6, MORPH_TOPHAT, kernel); imshow("tophat", dst6); } void my_blackhat(int, void*) { int s = step_size * 2 + 1; Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s)); morphologyEx(src, dst7, MORPH_BLACKHAT, kernel); imshow("blackhat", dst7); } int main() { src = imread("D:\\jing.png"); if (src.empty()) { cerr << "open error" << endl; return -1; } imshow("cat", src); my_dilate(0, 0); my_erode(0, 0); my_open(0, 0); my_close(0, 0); my_gradient(0, 0); my_tophat(0, 0); my_blackhat(0, 0); createTrackbar("erode_size", "erode", &step_size, max_size, my_erode); createTrackbar("erode_size", "dilate", &step_size, max_size,my_dilate); createTrackbar("erode_size", "open", &step_size, max_size, my_open); createTrackbar("erode_size", "close", &step_size, max_size, my_close); createTrackbar("erode_size", "gradient", &step_size, max_size, my_gradient); createTrackbar("erode_size", "tophat", &step_size, max_size, my_tophat); createTrackbar("erode_size", "blackhat", &step_size, max_size, my_blackhat); waitKey(0); }
原图:
dilate
白点不断变大
erode
白点逐渐变小
open
消除小物体;
在纤细处分离物体;
平滑较大的边界并不明显改变其面积
close
祛除小黑点
gradient
使轮廓更加清晰
顶帽
黑帽
Mat src,dst1, dst2; int step_size = 3; int max_size = 21; void my_dilate(int ,void*) { int s = step_size * 2 + 1; Mat structingElement = getStructuringElement(MORPH_ELLIPSE, Size(s, s), Point(-1, -1)); dilate(src, dst1, structingElement); imshow("dilate", dst1); return; } void my_erode(int, void*) { int s = step_size * 2 + 1; Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(s, s)); erode(src, dst2, kernel); imshow("erode", dst2); return; } int main() { src = imread("D:\\cat.jpg"); if (src.empty()) { cerr << "open error" << endl; return -1; } imshow("cat", src); my_dilate(0, 0); my_erode(0, 0); createTrackbar("erode_size", "erode", &step_size, max_size, my_erode); createTrackbar("膨胀:", "dilate", &step_size, max_size,my_dilate); waitKey(0); }
二值形态膨胀与腐蚀可转化为集合的逻辑运算,算法简单,适于并行处理,且易于硬件实现,适于对二值图像进行图像分割、细化、抽取骨架、边缘提取、形状分析。但是,在不同的应用场合,结构元素的选择及其相应的处理算法是不一样的,对不同的目标图像需设计不同的结构元素和不同的处理算法。结构元素的大小、形状选择合适与否,将直接影响图像的形态运算结果。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。