Skip to content

Commit 25b4cec

Browse files
committed
Add MedianFilterFogRemoval.cpp
1 parent b3aba83 commit 25b4cec

File tree

2 files changed

+203
-1
lines changed

2 files changed

+203
-1
lines changed

MedianFilterFogRemoval.cpp

+202
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
#include <opencv2/opencv.hpp>
2+
#include <iostream>
3+
#include <algorithm>
4+
#include <vector>
5+
using namespace cv;
6+
using namespace std;
7+
8+
int rows, cols;
9+
//获取最小值矩阵
10+
int **getMinChannel(cv::Mat img) {
11+
rows = img.rows;
12+
cols = img.cols;
13+
if (img.channels() != 3) {
14+
fprintf(stderr, "Input Error!");
15+
exit(-1);
16+
}
17+
int **imgGray;
18+
imgGray = new int *[rows];
19+
for (int i = 0; i < rows; i++) {
20+
imgGray[i] = new int[cols];
21+
}
22+
for (int i = 0; i < rows; i++) {
23+
for (int j = 0; j < cols; j++) {
24+
int loacalMin = 255;
25+
for (int k = 0; k < 3; k++) {
26+
if (img.at<Vec3b>(i, j)[k] < loacalMin) {
27+
loacalMin = img.at<Vec3b>(i, j)[k];
28+
}
29+
}
30+
imgGray[i][j] = loacalMin;
31+
}
32+
}
33+
return imgGray;
34+
}
35+
36+
//求暗通道
37+
int **getDarkChannel(int **img, int blockSize = 3) {
38+
if (blockSize % 2 == 0 || blockSize < 3) {
39+
fprintf(stderr, "blockSize is not odd or too small!");
40+
exit(-1);
41+
}
42+
//计算pool Size
43+
int poolSize = (blockSize - 1) / 2;
44+
int newHeight = rows + poolSize - 1;
45+
int newWidth = cols + poolSize - 1;
46+
int **imgMiddle;
47+
imgMiddle = new int *[newHeight];
48+
for (int i = 0; i < newHeight; i++) {
49+
imgMiddle[i] = new int[newWidth];
50+
}
51+
for (int i = 0; i < newHeight; i++) {
52+
for (int j = 0; j < newWidth; j++) {
53+
if (i < rows && j < cols) {
54+
imgMiddle[i][j] = img[i][j];
55+
}
56+
else {
57+
imgMiddle[i][j] = 255;
58+
}
59+
}
60+
}
61+
int **imgDark;
62+
imgDark = new int *[rows];
63+
for (int i = 0; i < rows; i++) {
64+
imgDark[i] = new int[cols];
65+
}
66+
int localMin = 255;
67+
for (int i = poolSize; i < newHeight - poolSize; i++) {
68+
for (int j = poolSize; j < newWidth - poolSize; j++) {
69+
for (int k = i - poolSize; k < i + poolSize + 1; k++) {
70+
for (int l = j - poolSize; l < j + poolSize + 1; l++) {
71+
if (imgMiddle[k][l] < localMin) {
72+
localMin = imgMiddle[k][l];
73+
}
74+
}
75+
}
76+
imgDark[i - poolSize][j - poolSize] = localMin;
77+
}
78+
}
79+
return imgDark;
80+
}
81+
82+
Mat MedianFilterFogRemoval(Mat src, float p = 0.95, int KernelSize = 41, int blockSize=3, bool meanModel = false, float percent = 0.001) {
83+
int row = src.rows;
84+
int col = src.cols;
85+
int** imgGray = getMinChannel(src);
86+
int **imgDark = getDarkChannel(imgGray, blockSize = blockSize);
87+
//int atmosphericLight = getGlobalAtmosphericLightValue(imgDark, src, meanModel = meanModel, percent = percent);
88+
int Histgram[256] = { 0 };
89+
for (int i = 0; i < row; i++) {
90+
for (int j = 0; j < col; j++) {
91+
Histgram[imgDark[i][j]]++;
92+
}
93+
}
94+
int Sum = 0, atmosphericLight = 0;
95+
for (int i = 255; i >= 0; i--) {
96+
Sum += Histgram[i];
97+
if (Sum > row * col * 0.01) {
98+
atmosphericLight = i;
99+
break;
100+
}
101+
}
102+
int SumB = 0, SumG = 0, SumR = 0, Amount = 0;
103+
//printf("%d\n", atmosphericLight);
104+
for (int i = 0; i < row; i++) {
105+
for (int j = 0; j < col; j++) {
106+
if (imgDark[i][j] >= atmosphericLight) {
107+
SumB += src.at<Vec3b>(i, j)[0];
108+
SumG += src.at<Vec3b>(i, j)[1];
109+
SumR += src.at<Vec3b>(i, j)[2];
110+
Amount++;
111+
}
112+
}
113+
}
114+
SumB /= Amount;
115+
SumG /= Amount;
116+
SumR /= Amount;
117+
Mat Filter(row, col, CV_8UC1);
118+
for (int i = 0; i < row; i++) {
119+
for (int j = 0; j < col; j++) {
120+
Filter.at<uchar>(i, j) = imgDark[i][j];
121+
}
122+
}
123+
Mat A(row, col, CV_8UC1);
124+
medianBlur(Filter, A, KernelSize);
125+
Mat temp(row, col, CV_8UC1);
126+
for (int i = 0; i < row; i++) {
127+
for (int j = 0; j < col; j++) {
128+
int Diff = Filter.at<uchar>(i, j) - A.at<uchar>(i, j);
129+
if (Diff < 0) Diff = -Diff;
130+
temp.at<uchar>(i, j) = Diff;
131+
}
132+
}
133+
medianBlur(temp, temp, KernelSize);
134+
Mat B(row, col, CV_8UC1);
135+
for (int i = 0; i < row; i++) {
136+
for (int j = 0; j < col; j++) {
137+
int Diff = A.at<uchar>(i, j) - temp.at<uchar>(i, j);
138+
if (Diff < 0) Diff = 0;
139+
B.at<uchar>(i, j) = Diff;
140+
}
141+
}
142+
for (int i = 0; i < row; i++) {
143+
for (int j = 0; j < col; j++) {
144+
int Min = B.at<uchar>(i, j) * p;
145+
if (imgDark[i][j] > Min) {
146+
B.at<uchar>(i, j) = Min;
147+
}
148+
else {
149+
B.at<uchar>(i, j) = imgDark[i][j];
150+
}
151+
}
152+
}
153+
Mat dst(row, col, CV_8UC3);
154+
for (int i = 0; i < row; i++) {
155+
for (int j = 0; j < col; j++) {
156+
int F = B.at<uchar>(i, j);
157+
int Value;
158+
if (SumB != F) {
159+
Value = SumB * (src.at<Vec3b>(i, j)[0] - F) / (SumB - F);
160+
}
161+
else {
162+
Value = src.at<Vec3b>(i, j)[0];
163+
}
164+
if (Value < 0) Value = 0;
165+
else if (Value > 255) Value = 255;
166+
dst.at<Vec3b>(i, j)[0] = Value;
167+
168+
if (SumG != F) {
169+
Value = SumG * (src.at<Vec3b>(i, j)[1] - F) / (SumG - F);
170+
}
171+
else {
172+
Value = src.at<Vec3b>(i, j)[1];
173+
}
174+
if (Value < 0) Value = 0;
175+
else if (Value > 255) Value = 255;
176+
dst.at<Vec3b>(i, j)[1] = Value;
177+
178+
if (SumR != F) {
179+
Value = SumR * (src.at<Vec3b>(i, j)[2] - F) / (SumR - F);
180+
}
181+
else {
182+
Value = src.at<Vec3b>(i, j)[2];
183+
}
184+
if (Value < 0) Value = 0;
185+
else if (Value > 255) Value = 255;
186+
dst.at<Vec3b>(i, j)[2] = Value;
187+
}
188+
}
189+
return dst;
190+
}
191+
192+
193+
int main() {
194+
cv::Mat src = cv::imread("F:\\fog\\7.jpg");
195+
rows = src.rows;
196+
cols = src.cols;
197+
cv::Mat dst = MedianFilterFogRemoval(src);
198+
cv::imshow("origin", src);
199+
cv::imshow("result", dst);
200+
cv::imwrite("F:\\fog\\res.jpg", dst);
201+
waitKey(0);
202+
}

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@
3030
- AutomaticWhiteBalanceMethod.cpp C++复现了《A Novel Automatic White Balance Method For Digital Still Cameras》这篇论文,实现了效果比完美反射更好得白平衡效果。原理请看:https://blog.csdn.net/just_sort/article/details/89183909
3131
- Automatic Color Equalization(ACE) and its Fast Implementation.cpp C++复现了IPOL《Automatic Color Equalization(ACE) and its Fast Implementation》论文,用于自动色彩均衡。原理请看:https://blog.csdn.net/just_sort/article/details/85237711
3232
- Single Image Haze Removal Using Dark Channel Prior(Guided Filter).cpp C++复现了《Single Image Haze Removal Using Dark Channel Prior》,但使用了何博士提到导向滤波来估计透射率,比原始实现效果更好。算法原理:https://blog.csdn.net/just_sort/article/details/89470403
33-
33+
- MedianFilterFogRemoval.cpp C++复现了《[一种单幅图像去雾方法](http://wenku.baidu.com/link?url=ZoNmd4noFbWZOGKCHus4anP83t8gcc0xWDu9QCfgQuzwn7LxUoBbZmMxrUAFYM3_YEMoQH3DdvYD8j1hdcHt5Wz4LhdvDe4_GZYXrqCYco3)》使用中值滤波进行去雾,原理请看:https://blog.csdn.net/just_sort/article/details/89520776

0 commit comments

Comments
 (0)