前言
这几个词语显得十分专业了,我刚接触的时候完全也不太明白,这些算法的目的和意义,但是自己查阅了很多资料,又自己编写了一下代码,发现其实并不是那么难理解。
纸上得来终觉浅,绝知此事要躬行。闲话少说了
一 概念
1 腐蚀
腐蚀这个词大家应该不陌生了,以前化学里面经常会提到这个词,大家回忆一下,就能明白,物体(一般是金属)的表面被酸性物质侵蚀,导致失去光泽之类,或者体积缩小。因为不是专业的找化学用语,只是大概说明这个意思。
那么图像腐蚀呢?简单的将就是原图像经过一个参考矩阵的腐蚀之后,图像的周边变小的一种操作。那下图 来说吧
腐蚀之后
可以看出来字体明显纤细了很多。那么怎么实现呢?看着十分的奇特。
本文参考下面两篇文章。
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 |
参考矩阵
也就是说 我们根据参考矩阵,然后找到灰度图中对应参考矩阵范围内,最小的那个值,将中间的值(标为红色)的变成最小值。
以下面蓝色区域为例子:
灰度图的像素
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 闭运算
先腐蚀, 在膨胀
效果图来自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的图片,但是腐蚀之后效果太恐怖了,就拿这只鱼做实验吧,下面是原始图片。
半径为11原始方法 |
半径为11本文方法 |
|
|
半径为11原始方法 |
半径为11本文方法 |
|
|