Skip to content

Commit 6a70563

Browse files
committed
Add MedianSideWindowFilter.cpp
1 parent 2ec196b commit 6a70563

File tree

2 files changed

+163
-0
lines changed

2 files changed

+163
-0
lines changed

MedianSideWindowFilter.cpp

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
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+
}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
- MedianFilterFogRemoval.cpp C++复现了《[一种单幅图像去雾方法](http://wenku.baidu.com/link?url=ZoNmd4noFbWZOGKCHus4anP83t8gcc0xWDu9QCfgQuzwn7LxUoBbZmMxrUAFYM3_YEMoQH3DdvYD8j1hdcHt5Wz4LhdvDe4_GZYXrqCYco3)》使用中值滤波进行去雾,原理请看:https://blog.csdn.net/just_sort/article/details/89520776
3636
- FastDefoggingBasedOnSingleImage.cpp C++复现了《基于单幅图像的快速去雾》论文,原理请看:https://blog.csdn.net/just_sort/article/details/90205686
3737
- BoxSideWindowFilter.cpp C++复现了CVPR2019《Side Window Filter》论文(Box Filter),实现霸气的强制保边,原理请看:https://blog.csdn.net/just_sort/article/details/93664078
38+
- MedianSideWindowFilter.cpp C++复现了CVPR2019《Side Window Filter》论文(Median Filter),实现霸气的强制保边,原理请看:https://blog.csdn.net/just_sort/article/details/93664078
3839

3940

4041

0 commit comments

Comments
 (0)