1
+ const float YCbCrYRF = 0 .299F ; // RGB转YCbCr的系数(浮点类型)
2
+ const float YCbCrYGF = 0 .587F ;
3
+ const float YCbCrYBF = 0 .114F ;
4
+ const float YCbCrCbRF = -0 .168736F ;
5
+ const float YCbCrCbGF = -0 .331264F ;
6
+ const float YCbCrCbBF = 0 .500000F ;
7
+ const float YCbCrCrRF = 0 .500000F ;
8
+ const float YCbCrCrGF = -0 .418688F ;
9
+ const float YCbCrCrBF = -0 .081312F ;
10
+
11
+ const float RGBRYF = 1 .00000F ; // YCbCr转RGB的系数(浮点类型)
12
+ const float RGBRCbF = 0 .0000F ;
13
+ const float RGBRCrF = 1 .40200F ;
14
+ const float RGBGYF = 1 .00000F ;
15
+ const float RGBGCbF = -0 .34414F ;
16
+ const float RGBGCrF = -0 .71414F ;
17
+ const float RGBBYF = 1 .00000F ;
18
+ const float RGBBCbF = 1 .77200F ;
19
+ const float RGBBCrF = 0 .00000F ;
20
+
21
+ const int Shift = 20 ;
22
+ const int HalfShiftValue = 1 << (Shift - 1 );
23
+
24
+ const int YCbCrYRI = (int )(YCbCrYRF * (1 << Shift) + 0.5 ); // RGB转YCbCr的系数(整数类型)
25
+ const int YCbCrYGI = (int )(YCbCrYGF * (1 << Shift) + 0.5 );
26
+ const int YCbCrYBI = (int )(YCbCrYBF * (1 << Shift) + 0.5 );
27
+ const int YCbCrCbRI = (int )(YCbCrCbRF * (1 << Shift) + 0.5 );
28
+ const int YCbCrCbGI = (int )(YCbCrCbGF * (1 << Shift) + 0.5 );
29
+ const int YCbCrCbBI = (int )(YCbCrCbBF * (1 << Shift) + 0.5 );
30
+ const int YCbCrCrRI = (int )(YCbCrCrRF * (1 << Shift) + 0.5 );
31
+ const int YCbCrCrGI = (int )(YCbCrCrGF * (1 << Shift) + 0.5 );
32
+ const int YCbCrCrBI = (int )(YCbCrCrBF * (1 << Shift) + 0.5 );
33
+
34
+ const int RGBRYI = (int )(RGBRYF * (1 << Shift) + 0.5 ); // YCbCr转RGB的系数(整数类型)
35
+ const int RGBRCbI = (int )(RGBRCbF * (1 << Shift) + 0.5 );
36
+ const int RGBRCrI = (int )(RGBRCrF * (1 << Shift) + 0.5 );
37
+ const int RGBGYI = (int )(RGBGYF * (1 << Shift) + 0.5 );
38
+ const int RGBGCbI = (int )(RGBGCbF * (1 << Shift) + 0.5 );
39
+ const int RGBGCrI = (int )(RGBGCrF * (1 << Shift) + 0.5 );
40
+ const int RGBBYI = (int )(RGBBYF * (1 << Shift) + 0.5 );
41
+ const int RGBBCbI = (int )(RGBBCbF * (1 << Shift) + 0.5 );
42
+ const int RGBBCrI = (int )(RGBBCrF * (1 << Shift) + 0.5 );
43
+
44
+ Mat RGB2YCbCr (Mat src) {
45
+ int row = src.rows ;
46
+ int col = src.cols ;
47
+ Mat dst (row, col, CV_8UC3);
48
+ for (int i = 0 ; i < row; i++) {
49
+ for (int j = 0 ; j < col; j++) {
50
+ int Blue = src.at <Vec3b>(i, j)[0 ];
51
+ int Green = src.at <Vec3b>(i, j)[1 ];
52
+ int Red = src.at <Vec3b>(i, j)[2 ];
53
+ dst.at <Vec3b>(i, j)[0 ] = (int )((YCbCrYRI * Red + YCbCrYGI * Green + YCbCrYBI * Blue + HalfShiftValue) >> Shift);
54
+ dst.at <Vec3b>(i, j)[1 ] = (int )(128 + ((YCbCrCbRI * Red + YCbCrCbGI * Green + YCbCrCbBI * Blue + HalfShiftValue) >> Shift));
55
+ dst.at <Vec3b>(i, j)[2 ] = (int )(128 + ((YCbCrCrRI * Red + YCbCrCrGI * Green + YCbCrCrBI * Blue + HalfShiftValue) >> Shift));
56
+ }
57
+ }
58
+ return dst;
59
+ }
60
+
61
+ Mat YCbCr2RGB (Mat src) {
62
+ int row = src.rows ;
63
+ int col = src.cols ;
64
+ Mat dst (row, col, CV_8UC3);
65
+ for (int i = 0 ; i < row; i++) {
66
+ for (int j = 0 ; j < col; j++) {
67
+ int Y = src.at <Vec3b>(i, j)[0 ];
68
+ int Cb = src.at <Vec3b>(i, j)[1 ] - 128 ;
69
+ int Cr = src.at <Vec3b>(i, j)[2 ] - 128 ;
70
+ int Red = Y + ((RGBRCrI * Cr + HalfShiftValue) >> Shift);
71
+ int Green = Y + ((RGBGCbI * Cb + RGBGCrI * Cr + HalfShiftValue) >> Shift);
72
+ int Blue = Y + ((RGBBCbI * Cb + HalfShiftValue) >> Shift);
73
+ if (Red > 255 ) Red = 255 ; else if (Red < 0 ) Red = 0 ;
74
+ if (Green > 255 ) Green = 255 ; else if (Green < 0 ) Green = 0 ; // 编译后应该比三目运算符的效率高
75
+ if (Blue > 255 ) Blue = 255 ; else if (Blue < 0 ) Blue = 0 ;
76
+ dst.at <Vec3b>(i, j)[0 ] = Blue;
77
+ dst.at <Vec3b>(i, j)[1 ] = Green;
78
+ dst.at <Vec3b>(i, j)[2 ] = Red;
79
+ }
80
+ }
81
+ return dst;
82
+ }
83
+
84
+ Mat AutomaticWhiteBalanceMethod (Mat src) {
85
+ int row = src.rows ;
86
+ int col = src.cols ;
87
+ if (src.channels () == 4 ) {
88
+ cvtColor (src, src, CV_BGRA2BGR);
89
+ }
90
+ Mat input = RGB2YCbCr (src);
91
+ Mat mark (row, col, CV_8UC1);
92
+ int sum = 0 ;
93
+ for (int i = 0 ; i < row; i+=100 ) {
94
+ for (int j = 0 ; j < col; j+=100 ) {
95
+ if (i + 100 < row && j + 100 < col) {
96
+ Rect rect (j, i, 100 , 100 );
97
+ Mat temp = input (rect);
98
+ Scalar global_mean = mean (temp);
99
+ double dr = 0 , db = 0 ;
100
+ for (int x = 0 ; x < 100 ; x++) {
101
+ uchar *ptr = temp.ptr <uchar>(x) + 1 ;
102
+ for (int y = 0 ; y < 100 ; y++) {
103
+ dr += pow (abs (*ptr - global_mean[1 ]), 2 );
104
+ ptr++;
105
+ db += pow (abs (*ptr - global_mean[2 ]), 2 );
106
+ ptr++;
107
+ ptr++;
108
+ }
109
+ }
110
+ dr /= 10000 ;
111
+ db /= 10000 ;
112
+ double cr_left_criteria = 1.5 * global_mean[1 ] + dr * global_mean[1 ];
113
+ double cr_right_criteria = 1.5 * dr;
114
+ double cb_left_criteria = global_mean[2 ] + db * global_mean[2 ];
115
+ double cb_right_criteria = 1.5 * db;
116
+ for (int x = 0 ; x < 100 ; x++) {
117
+ uchar *ptr = temp.ptr <uchar>(x) + 1 ;
118
+ for (int y = 0 ; y < 100 ; y++) {
119
+ uchar cr = *ptr;
120
+ ptr++;
121
+ uchar cb = *ptr;
122
+ ptr++;
123
+ ptr++;
124
+ if ((cr - cb_left_criteria) < cb_right_criteria && (cb - cr_left_criteria) < cr_right_criteria) {
125
+ sum++;
126
+ mark.at <uchar>(i + x, j + y) = 1 ;
127
+ }
128
+ else {
129
+ mark.at <uchar>(i + x, j + y) = 0 ;
130
+ }
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
136
+
137
+ int Threshold = 0 ;
138
+ int Ymax = 0 ;
139
+ int Light[256 ] = { 0 };
140
+ for (int i = 0 ; i < row; i++) {
141
+ for (int j = 0 ; j < col; j++) {
142
+ if (mark.at <uchar>(i, j) == 1 ) {
143
+ Light[(int )(input.at <Vec3b>(i, j)[0 ])]++;
144
+ }
145
+ Ymax = max (Ymax, (int )(input.at <Vec3b>(i, j)[0 ]));
146
+ }
147
+ }
148
+ printf (" maxY: %d\n " , Ymax);
149
+ int sum2 = 0 ;
150
+ for (int i = 255 ; i >= 0 ; i--) {
151
+ sum2 += Light[i];
152
+ if (sum2 >= sum * 0.1 ) {
153
+ Threshold = i;
154
+ break ;
155
+ }
156
+ }
157
+ printf (" Threshold: %d\n " , Threshold);
158
+ printf (" Sum: %d Sum2: %d\n " , sum, sum2);
159
+ double Blue = 0 ;
160
+ double Green = 0 ;
161
+ double Red = 0 ;
162
+ int cnt2 = 0 ;
163
+ for (int i = 0 ; i < row; i++) {
164
+ for (int j = 0 ; j < col; j++) {
165
+ if (mark.at <uchar>(i, j) == 1 && (int )(input.at <Vec3b>(i, j)[0 ]) >= Threshold) {
166
+ Blue += 1.0 * src.at <Vec3b>(i, j)[0 ];
167
+ Green += 1.0 * src.at <Vec3b>(i, j)[1 ];
168
+ Red += 1.0 * src.at <Vec3b>(i, j)[2 ];
169
+ cnt2++;
170
+ }
171
+ }
172
+ }
173
+ Blue /= cnt2;
174
+ Green /= cnt2;
175
+ Red /= cnt2;
176
+ printf (" %.5f %.5f %.5f\n " , Blue, Green, Red);
177
+ Mat dst (row, col, CV_8UC3);
178
+ double maxY = Ymax;
179
+ for (int i = 0 ; i < row; i++) {
180
+ for (int j = 0 ; j < col; j++) {
181
+ int B = (int )(maxY * src.at <Vec3b>(i, j)[0 ] / Blue);
182
+ int G = (int )(maxY * src.at <Vec3b>(i, j)[1 ] / Green);
183
+ int R = (int )(maxY * src.at <Vec3b>(i, j)[2 ] / Red);
184
+ if (B > 255 ) B = 255 ; else if (B < 0 ) B = 0 ;
185
+ if (G > 255 ) G = 255 ; else if (G < 0 ) G = 0 ;
186
+ if (R > 255 ) R = 255 ; else if (R < 0 ) R = 0 ;
187
+ dst.at <Vec3b>(i, j)[0 ] = B;
188
+ dst.at <Vec3b>(i, j)[1 ] = G;
189
+ dst.at <Vec3b>(i, j)[2 ] = R;
190
+ }
191
+ }
192
+ return dst;
193
+ }
0 commit comments