平滑空间滤波

图像处理中的空间滤波主要有2种类型,平滑空间滤波和锐化空间滤波。平滑空间滤波一般用于模糊图像,比如消除散乱的噪声点等。平滑空间滤波主要有均值滤波和中值滤波,以及其余的复杂统计方法。滤波窗口的大小可以选为33或者44或者5*5等。
其实不同的空间滤波处理基本上就滤波窗口的系数不相同,除了均值滤波要除以滤波窗口大小以及中值滤波要特殊处理之外,那么我们可以实现一个针对特定滤波窗口实现的滤波公共函数。比如,均值滤波窗口

{1,1,1}

{1,1,1},

{1,1,1}

就是选取当前像素点周围9个点的像素值总和再除以9得到的。而中值滤波则必须得到这9个值中排行第5的值作为当前像素的值。平滑滤波的原理也比较简单。下面给出相关的代码。

滤波基础函数,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//传入滤波窗口系数和尺寸(nSize*nSize)
void CxBitmap::Filter(double* pfFactors, int nSize, BOOL bAve)
{
double fMedian = 0;
int nRead = 0;
int nRadius = nSize / 2;//滤波窗口的半径
int nBytePerPixel = bitmapinfoheader.biBitCount / 8;
int i, j, k, m, n;

//拷贝边界到临时缓存区
for (i = 0; i < nRadius; ++i)
{
memcpy(pbyTmpBuffer + i * m_nBytesPerLine, pbyBuffer + i * m_nBytesPerLine,
m_nBytesPerLine);
memcpy(pbyTmpBuffer + (bitmapinfoheader.biHeight - 1 - i) * m_nBytesPerLine,
pbyBuffer + (bitmapinfoheader.biHeight - 1 - i) * m_nBytesPerLine,
m_nBytesPerLine);
}

for (i = 0; i < bitmapinfoheader.biHeight; ++i)
{
nRead = i * m_nBytesPerLine;
for (j = 0; j < nRadius; ++j)
{
pbyTmpBuffer[nRead] = pbyBuffer[nRead++];
pbyTmpBuffer[nRead] = pbyBuffer[nRead++];
pbyTmpBuffer[nRead] = pbyBuffer[nRead++];
}

nRead = i * m_nBytesPerLine + nBytePerPixel * (bitmapinfoheader.biWidth - nRadius);
for (j = 0; j < nRadius; ++j)
{
pbyTmpBuffer[nRead] = pbyBuffer[nRead++];
pbyTmpBuffer[nRead] = pbyBuffer[nRead++];
pbyTmpBuffer[nRead] = pbyBuffer[nRead++];
}
}

for (i = nRadius; i < bitmapinfoheader.biHeight - nRadius; ++i)
{
nRead = i * m_nBytesPerLine + nRadius * nBytePerPixel;
for (j = nRadius; j < bitmapinfoheader.biWidth - nRadius; ++j)
{
for (k = 0; k < m_nBytesPerPixel; ++k)
{
fMedian = 0;
for (m = 0; m < nSize; ++m)
{
for (n = 0; n < nSize; ++n)
{
fMedian += *(pfFactors + nSize * m + n) * pbyBuffer[nRead + (m - nRadius) * m_nBytesPerLine + (n - nRadius) * nBytePerPixel];
}
}
if (bAve)
{
fMedian /= nSize * nSize;
}
//assert(nMedian >= 0);
//注意必须处理变换后不在0-255范围内的像素
if (fMedian < 0)
{
fMedian = 0;
}
if (fMedian > 255)
{
fMedian = 255;
}
pbyTmpBuffer[nRead++] = fMedian;
}
}
}

m_bBinary = FALSE;//滤波处理之后肯定不是二值图像了
memcpy(pbyBuffer, pbyTmpBuffer, bitmapinfoheader.biSizeImage);
}

均值滤波函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//8邻域滤波均值滤波
void CxBitmap::AverageFilter()
{
const int AVE_NEIGHBOUR_SIZE = 3;
static double s_fAveFactors[AVE_NEIGHBOUR_SIZE][AVE_NEIGHBOUR_SIZE] =
{
{1, 1, 1},
{1, 1, 1},
{1, 1, 1},
};
assert(m_bLoad);
if (m_bLoad)
{
Filter(s_fAveFactors[0], AVE_NEIGHBOUR_SIZE, TRUE);
}
}