1
+ // 针对灰度图的中值滤波+CVPR 2019的SideWindowFilter
2
+ // 其他种类的滤波直接换核即可
3
+
4
+ // 记录每一个方向的核的不为0的元素个数
5
+ int cnt[8 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 };
6
+ // 记录每一个方向的滤波器
7
+ vector <int > filter[8 ];
8
+
9
+ // 初始化半径为radius的滤波器,原理可以看https://mp.weixin.qq.com/s/vjzZjRoQw7MnkqAfvwBUNA
10
+ void InitFilter (int radius) {
11
+ int n = radius * 2 + 1 ;
12
+ for (int i = 0 ; i < 8 ; i++) {
13
+ cnt[i] = 0 ;
14
+ filter[i].clear ();
15
+ }
16
+ for (int i = 0 ; i < 8 ; i++) {
17
+ for (int x = 0 ; x < n; x++) {
18
+ for (int y = 0 ; y < n; y++) {
19
+ if (i == 0 && x <= radius && y <= radius) {
20
+ filter[i].push_back (1 );
21
+ }
22
+ else if (i == 1 && x <= radius && y >= radius) {
23
+ filter[i].push_back (1 );
24
+ }
25
+ else if (i == 2 && x >= radius && y <= radius) {
26
+ filter[i].push_back (1 );
27
+ }
28
+ else if (i == 3 && x >= radius && y >= radius) {
29
+ filter[i].push_back (1 );
30
+ }
31
+ else if (i == 4 && x <= radius) {
32
+ filter[i].push_back (1 );
33
+ }
34
+ else if (i == 5 && x >= radius) {
35
+ filter[i].push_back (1 );
36
+ }
37
+ else if (i == 6 && y >= radius) {
38
+ filter[i].push_back (1 );
39
+ }
40
+ else if (i == 7 && y <= radius) {
41
+ filter[i].push_back (1 );
42
+ }
43
+ else {
44
+ filter[i].push_back (0 );
45
+ }
46
+ }
47
+ }
48
+ }
49
+ for (int i = 0 ; i < 8 ; i++) {
50
+ int sum = 0 ;
51
+ for (int j = 0 ; j < filter[i].size (); j++) sum += filter[i][j] == 1 ;
52
+ cnt[i] = sum;
53
+ }
54
+ }
55
+
56
+ // 实现Side Window Filter的中值滤波,强制保边
57
+ Mat MedianSideWindowFilter (Mat src, int radius = 1 ) {
58
+ int row = src.rows ;
59
+ int col = src.cols ;
60
+ int channels = src.channels ();
61
+ InitFilter (radius);
62
+ // 针对灰度图
63
+ if (channels == 1 ) {
64
+ Mat dst (row, col, CV_8UC1);
65
+ for (int i = 0 ; i < row; i++) {
66
+ for (int j = 0 ; j < col; j++) {
67
+ if (i < radius || i + radius >= row || j < radius || j + radius >= col) {
68
+ dst.at <uchar>(i, j) = src.at <uchar>(i, j);
69
+ continue ;
70
+ }
71
+ int minn = 256 ;
72
+ int pos = 0 ;
73
+ for (int k = 0 ; k < 8 ; k++) {
74
+ int val = 0 ;
75
+ int id = 0 ;
76
+ vector <int > now;
77
+ for (int x = -radius; x <= radius; x++) {
78
+ for (int y = -radius; y <= radius; y++) {
79
+ // if (x == 0 && y == 0) continue;
80
+ now.push_back (src.at <uchar>(i + x, j + y) * filter[k][id++]);
81
+ // val += src.at<uchar>(i + x, j + y) * filter[k][id++];
82
+ }
83
+ }
84
+ sort (now.begin (), now.end ());
85
+ val = now[(2 * radius + 1 )*(2 * radius + 1 ) / 2 ];
86
+ if (abs (val - src.at <uchar>(i, j)) < minn) {
87
+ minn = abs (val - src.at <uchar>(i, j));
88
+ pos = k;
89
+ }
90
+ }
91
+ int val = 0 ;
92
+ int id = 0 ;
93
+ vector <int > now;
94
+ for (int x = -radius; x <= radius; x++) {
95
+ for (int y = -radius; y <= radius; y++) {
96
+ // if (x == 0 && y == 0) continue;
97
+ now.push_back (src.at <uchar>(i + x, j + y) * filter[pos][id++]);
98
+ // val += src.at<uchar>(i + x, j + y) * filter[k][id++];
99
+ }
100
+ }
101
+ sort (now.begin (), now.end ());
102
+ val = now[(2 * radius + 1 )*(2 * radius + 1 ) / 2 ];
103
+ dst.at <uchar>(i, j) = val;
104
+ }
105
+ }
106
+ return dst;
107
+ }
108
+ // 针对RGB图
109
+ Mat dst (row, col, CV_8UC3);
110
+ for (int c = 0 ; c < 3 ; c++) {
111
+ for (int i = 0 ; i < row; i++) {
112
+ for (int j = 0 ; j < col; j++) {
113
+ if (i < radius || i + radius >= row || j < radius || j + radius >= col) {
114
+ dst.at <Vec3b>(i, j)[c] = src.at <Vec3b>(i, j)[c];
115
+ continue ;
116
+ }
117
+ int minn = 256 ;
118
+ int pos = 0 ;
119
+ for (int k = 0 ; k < 8 ; k++) {
120
+ int val = 0 ;
121
+ int id = 0 ;
122
+ vector <int > now;
123
+ for (int x = -radius; x <= radius; x++) {
124
+ for (int y = -radius; y <= radius; y++) {
125
+ // if (x == 0 && y == 0) continue;
126
+ // val += src.at<Vec3b>(i + x, j + y)[c] * filter[k][id++];
127
+ now.push_back (src.at <Vec3b>(i + x, j + y)[c] * filter[k][id++]);
128
+ }
129
+ }
130
+ val = now[(2 * radius + 1 )*(2 * radius + 1 ) / 2 ];
131
+ if (abs (val - src.at <Vec3b>(i, j)[c]) < minn) {
132
+ minn = abs (val - src.at <Vec3b>(i, j)[c]);
133
+ pos = k;
134
+ }
135
+ }
136
+ int val = 0 ;
137
+ int id = 0 ;
138
+ vector <int > now;
139
+ for (int x = -radius; x <= radius; x++) {
140
+ for (int y = -radius; y <= radius; y++) {
141
+ // if (x == 0 && y == 0) continue;
142
+ // val += src.at<Vec3b>(i + x, j + y)[c] * filter[k][id++];
143
+ now.push_back (src.at <Vec3b>(i + x, j + y)[c] * filter[pos][id++]);
144
+ }
145
+ }
146
+ val = now[(2 * radius + 1 )*(2 * radius + 1 ) / 2 ];
147
+ dst.at <Vec3b>(i, j)[c] = val;
148
+ }
149
+ }
150
+ }
151
+ return dst;
152
+ }
153
+
154
+
155
+ int main () {
156
+ Mat src = imread (" F:\\ 1.jpg" );
157
+ for (int i = 0 ; i < 10 ; i++) {
158
+ src = MedianSideWindowFilter (src, 3 );
159
+ }
160
+ imwrite (" F:\\ res.jpg" , src);
161
+ return 0 ;
162
+ }
0 commit comments