高斯平滑和中值滤波

高斯平滑

可以认为是使用高斯模板加权的均值滤波。(关于高斯模板)

这里使用3x3的模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
uchar GetMean(uchar* image, int width, int height, int r, int c)
{
double gray =
0.0947416 * image[(r - 1) * width + c - 1] +
0.118318 * image[(r - 1) * width + c] +
0.0947416 * image[(r - 1) * width + c + 1] +

0.118318 * image[r * width + c - 1] +
0.147761 * image[r * width + c] +
0.118318 * image[r * width + c + 1] +

0.0947416 * image[(r + 1) * width + c - 1] +
0.118318 * image[(r + 1) * width + c] +
0.0947416 * image[(r + 1) * width + c + 1];
return (uchar)gray;
}

对256色BMP灰度图进行处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int height = m_dib->m_height;
int width = m_dib->m_width;
uchar* image = m_dib->m_BMPdata;
uchar* newImage = new uchar[height * width];
for (int i{ 1 }; i < height - 1; i++) {
for (int j{ 1 }; j < width - 1; j++) {
newImage[width * i + j] = GetMean(image, width, height, i, j);
}
}
// 边缘直接赋值
for (int i : {0, height - 1}) {
for (int j{ 0 }; j < width - 1; j++) {
newImage[width * i + j] = image[width * i + j];
}
}
for (int j : {0, width - 1}) {
for (int i{ 0 }; i < height - 1; i++) {
newImage[width * i + j] = image[width * i + j];
}
}

m_dib->m_BMPdata = newImage;

中值滤波

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
// 返回数组的中值
uchar GetMid(const uchar* arr, int len)
{
uchar res{ arr[0] };
// 计数法快速求中值
int count[256]{ 0 };
for (int i{ 0 }; i < len; i++) {
count[(int)arr[i]]++;
}
int mid = len / 2 + 1;
int cnt{ 0 };
for (int i{ 0 }; i < 256; i++) {
cnt += count[i];
if (cnt >= mid) {
res = i;
break;
}
}
return res;
}

// 3x3的中值
uchar GetMid(const uchar* image, int width, int height, int r, int c)
{
uchar tmp[9] = {
image[(r - 1) * width + c - 1],
image[(r - 1) * width + c],
image[(r - 1) * width + c + 1],

image[r * width + c - 1],
image[r * width + c],
image[r * width + c + 1],

image[(r + 1) * width + c - 1],
image[(r + 1) * width + c],
image[(r + 1) * width + c + 1]
};
return GetMid(tmp, 9);
}

对256色灰度图像进行处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for (int i{ 2 }; i < height - 2; i++) {
for (int j{ 2 }; j < width - 2; j++) {
newImage[width * i + j] = GetMid(image, width, height, i, j);
}
}
// 边缘直接赋值
for (int i : {0, 1, height - 2, height - 1}) {
for (int j{ 0 }; j < width; j++) {
newImage[width * i + j] = image[width * i + j];
}
}
for (int j : {0, 1, width - 2, width - 1}) {
for (int i{ 0 }; i < height; i++) {
newImage[width * i + j] = image[width * i + j];
}
}