11315:灰度字符画降噪
题目
依据四邻域规则修正孤立灰度值,并把取值 0~9 的二维图像写成字符画。
解析
函数不会修改像素数组,因此每个位置读取到的始终是原图数据,降噪不会沿遍历方向传播。尺寸和所有像素在首次写入前统一检查,使参数错误不会留下部分输出。
一个位置最多有四个相邻值。先累计实际存在的相邻值,同时判断当前值是否与每一个相邻值都相差 1 以上;条件成立时,用 (sum + count / 2) / count 完成非负整数的四舍五入。
解析
c
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
typedef enum {
DIGIT_IMAGE_OK,
DIGIT_IMAGE_INVALID,
DIGIT_IMAGE_WRITE_ERROR
} DigitImageResult;
static unsigned int distance_between(
unsigned int left,
unsigned int right
) {
return left > right ? left - right : right - left;
}
static void include_neighbor(
unsigned int current,
unsigned int neighbor,
unsigned int *sum,
unsigned int *count,
bool *replace
) {
*sum += neighbor;
++*count;
if (distance_between(current, neighbor) <= 1) {
*replace = false;
}
}
static unsigned int denoised_at(
const unsigned char *pixels,
size_t width,
size_t height,
size_t row,
size_t column
) {
size_t index = row * width + column;
unsigned int current = pixels[index];
unsigned int sum = 0;
unsigned int count = 0;
bool replace = true;
if (row > 0) {
include_neighbor(
current,
pixels[index - width],
&sum,
&count,
&replace
);
}
if (row + 1 < height) {
include_neighbor(
current,
pixels[index + width],
&sum,
&count,
&replace
);
}
if (column > 0) {
include_neighbor(
current,
pixels[index - 1],
&sum,
&count,
&replace
);
}
if (column + 1 < width) {
include_neighbor(
current,
pixels[index + 1],
&sum,
&count,
&replace
);
}
if (count == 0 || !replace) {
return current;
}
return (sum + count / 2) / count;
}
DigitImageResult write_denoised_digit_image(
FILE *output,
const unsigned char *pixels,
size_t width,
size_t height
) {
static const char palette[] = " .:-=+*#%@";
if (output == NULL
|| pixels == NULL
|| width == 0
|| height == 0
|| width > SIZE_MAX / height) {
return DIGIT_IMAGE_INVALID;
}
size_t pixel_count = width * height;
for (size_t i = 0; i < pixel_count; ++i) {
if (pixels[i] > 9) {
return DIGIT_IMAGE_INVALID;
}
}
for (size_t row = 0; row < height; ++row) {
for (size_t column = 0; column < width; ++column) {
unsigned int value = denoised_at(
pixels,
width,
height,
row,
column
);
if (fputc(
(unsigned char)palette[value],
output
) == EOF) {
return DIGIT_IMAGE_WRITE_ERROR;
}
}
if (fputc('\n', output) == EOF) {
return DIGIT_IMAGE_WRITE_ERROR;
}
}
if (fflush(output) == EOF) {
return DIGIT_IMAGE_WRITE_ERROR;
}
return DIGIT_IMAGE_OK;
}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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140