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
+ }
0 commit comments