http://blog.csdn.net/u011021773/article/details/53065120
上一篇我讲过什么叫做卷积,而且提到了卷积与滤波其实不完全相同,因为部分滤波是非线性的,比方说中值滤波,就是取每个局部地区的中位数,也就是中间大小的数。如果展开了类比,如果取局部最大值或者局部最小值会是什么样的呢?大值滤波?小值滤波?
哈哈,其实取大值滤波的官方学名叫做膨胀,小值滤波叫做腐蚀。一句话概括,膨胀就是取局部最大值的滤波,腐蚀就是取局部最小值的滤波。
话不多讲,来上一段膨胀的代码:
Mat MyDilate(Mat src, int KernelSize=3,int step=1)
{
Mat dst(src.rows,src.cols,src.type());
src.copyTo(dst);
//半个核的大小,用以计算滤波中心
int KernelHalfSize = (KernelSize - 1) / 2;
if (0 == KernelHalfSize)
{
return dst;
}
int channels = src.channels();
//膨胀是求最大值的滤波
for (int c = 0; c < channels; c++)
{
for (int col = 0; col < src.cols; col+=step)
{
for (int row = 0; row < src.rows; row+=step)
{
int max = 0;
for (int kc = col-KernelHalfSize; kc < col+KernelHalfSize; kc ++)
{
for (int kr = row- KernelHalfSize; kr < row+KernelHalfSize; kr ++)
{
if (src.at<Vec3b>(mid(kr, 0, src.rows-1), mid(kc, 0, src.cols-1))[c] > max)
{
//如果是彩色图
if (3 == channels)
{
//这里求三个数的中位数是为了解决滤波边界的问题,
//如果超出界限的就选边界那一点的值,因为是求最大值所以某个点多算几次也没有关系
max = src.at<Vec3b>(mid(kr, 0, src.rows-1), mid(kc, 0, src.cols-1))[c];
}
//如果是灰度图
else if (1 == channels)
{
max = src.at<uchar>(mid(kr, 0, src.rows-1), mid(kc, 0, src.cols-1));
}
}
}
}
if (3 == channels)
{
dst.at<Vec3b>(row,col)[c] = max;
}
//如果是灰度图
else if (1 == channels)
{
dst.at<uchar>(row,col) = max;
}
}
}
}
return dst;
}