图像处理算法系列 第六章 图像形态变化 膨胀 腐蚀 开运算 闭运算

前言

这几个词语显得十分专业了,我刚接触的时候完全也不太明白,这些算法的目的和意义,但是自己查阅了很多资料,又自己编写了一下代码,发现其实并不是那么难理解。

纸上得来终觉浅,绝知此事要躬行。闲话少说了


一 概念


1  腐蚀
   腐蚀这个词大家应该不陌生了,以前化学里面经常会提到这个词,大家回忆一下,就能明白,物体(一般是金属)的表面被酸性物质侵蚀,导致失去光泽之类,或者体积缩小。因为不是专业的找化学用语,只是大概说明这个意思。
    那么图像腐蚀呢?简单的将就是原图像经过一个参考矩阵的腐蚀之后,图像的周边变小的一种操作。那下图 来说吧

                         图像处理算法系列 第六章 图像形态变化 膨胀 腐蚀 开运算 闭运算_第1张图片           腐蚀之后   图像处理算法系列 第六章 图像形态变化 膨胀 腐蚀 开运算 闭运算_第2张图片

    可以看出来字体明显纤细了很多。那么怎么实现呢?看着十分的奇特。

     本文参考下面两篇文章。
http://www.cnblogs.com/maozefa/archive/2011/12/10/2283517.html
http://vipbase.net/ipbook/chap06.htm

嘿嘿,转载需要声明一下,尊重别人的劳动哈。

我自己理解了一下,腐蚀这个词确实很生动。 腐蚀的目标就是原图像, 腐蚀的酸性物质就是我们需要创建的矩阵。我们通过创建的矩阵将原图像进行了腐蚀。
本文只讲腐蚀矩阵是长方形的,其他形状的原理是类似的。上面的两个文章中都是对二值化之后进行操作,实际上可以扩展到所有图像。不一定要二值化。

以灰度图为例子吧,简单一点

灰度图的像素
30 30 40 50 70
40 50 60 70 20
30 50 80 20 25
33 44 66 77 99
44 66 88 99 22

参考矩阵 
1 1 1
1 1 1
1 1 1

也就是说 我们根据参考矩阵,然后找到灰度图中对应参考矩阵范围内,最小的那个值,将中间的值(标为红色)的变成最小值。

以下面蓝色区域为例子:

灰度图的像素
30 30 40 50 70
40 50 60 70 20
30 50 80 20 25
33 44 66 77 99
44 66 88 99 22

可以看到蓝色区域内最小值是20,则将中间的60变成20.
结果如下:


灰度图的像素
30 30 40 50 70
40 50 20 70 20
30 50 80 20 25
33 44 66 77 99
44 66 88 99 22
将上面的图片都经过刚才的操作,可以得到下面的结果

灰度图的像素
30 30 40 50 70
40 30 30 20 20
30 30 20 20 25
33 33 20 20 99
44 66 88 99 22

可以看到中间的区域都发生了变化,之前我犯了个错误,以为每次腐蚀完之后,在目标图像上进一步腐蚀,那样整个图片颜色不都一样了么?其实腐蚀的操作源应该一直是原始图像。


2 膨胀
  这个我就不细讲了,和腐蚀是逆运算,改两行代码就行了 直接上图了
图像处理算法系列 第六章 图像形态变化 膨胀 腐蚀 开运算 闭运算_第3张图片   膨胀 图像处理算法系列 第六章 图像形态变化 膨胀 腐蚀 开运算 闭运算_第4张图片

3 开运算
   就是先膨胀, 再腐蚀
图像处理算法系列 第六章 图像形态变化 膨胀 腐蚀 开运算 闭运算_第5张图片
4 闭运算
先腐蚀, 在膨胀
图像处理算法系列 第六章 图像形态变化 膨胀 腐蚀 开运算 闭运算_第6张图片

效果图来自opencv。

三 代码

void ErosionImage(Mat src, Mat &dst, int size)
{
	dst.create(src.size(),src.type());
	uchar *p, *q;

	int maskRows = 2*size + 1;
	int maskCols = 2*size + 1;

	int channels = src.channels();
	int rows = src.rows;
	int cols = src.cols;

	for (int i = 0 ; i< rows - maskRows; i++)
	{

		p = src.ptr<uchar>(i);
		for (int j = 0; j < cols - maskCols ;j++)
		{
			uchar minB = p[(j + maskCols /2)*channels ];
			uchar minG = p[(j + maskCols /2)*channels + 1];
			uchar minR = p[(j + maskCols /2)*channels + 2];

			for (int k = 0; k <maskRows;k++)
			{
				p = src.ptr<uchar>(i+k);
				for (int l = 0; l< maskCols;l++)
				{
					//if (p[(l+j) *channels] < minB  &&p[(l+j)*channels+1] < minG &&p[(l+j)*channels+2] < minR)写错了,之前的判断。
                                        if (p[(l+j) *channels] + p[(l+j)*channels+1]+p[(l+j)*channels+2] < minB + minG +  minR )
					{
						minB = p[(l+j) *channels];	
						minG = p[(l+j) *channels+1];
						minR = p[(l+j) *channels+2];
					}
				}
			}
			
			q = dst.ptr<uchar>(i + maskRows/2);
			q[(j + maskCols /2)*channels ] = minB;
			q[(j + maskCols /2)*channels +1] = minG;
			q[(j + maskCols /2)*channels + 2] = minR;
		}
	}
}

将上面红色那行小于号改成大于号 就是膨胀算法

if if (p[(l+j) *channels] + p[(l+j)*channels+1]+p[(l+j)*channels+2] < minB + minG +  minR )

这里就不写了。

四效果

本来想放lena的图片,但是腐蚀之后效果太恐怖了,就拿这只鱼做实验吧,下面是原始图片。
图像处理算法系列 第六章 图像形态变化 膨胀 腐蚀 开运算 闭运算_第7张图片

半径为11原始方法 半径为11本文方法
图像处理算法系列 第六章 图像形态变化 膨胀 腐蚀 开运算 闭运算_第8张图片 图像处理算法系列 第六章 图像形态变化 膨胀 腐蚀 开运算 闭运算_第9张图片


半径为11原始方法 半径为11本文方法
图像处理算法系列 第六章 图像形态变化 膨胀 腐蚀 开运算 闭运算_第10张图片 图像处理算法系列 第六章 图像形态变化 膨胀 腐蚀 开运算 闭运算_第11张图片




你可能感兴趣的:(算法,opencv,图像处理,形态学,腐)