Skip to content

Commit 3bd7d8b

Browse files
committed
Add AutomaticWhiteBalanceMethod.cpp
1 parent 104fa6c commit 3bd7d8b

File tree

2 files changed

+195
-0
lines changed

2 files changed

+195
-0
lines changed

AutomaticWhiteBalanceMethod.cpp

+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
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+
}

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,5 @@
2727
- unevenLightCompensate.cpp C++复现了《一种基于亮度均衡的图像阈值分割技术》这篇论文的光照补偿部分,可以对光照不均匀,曝光,逆光图像做亮度均衡,效果不错。原理请看:https://blog.csdn.net/just_sort/article/details/88551771
2828
- Adaptive correction algorithm for illumination inhomogeneity image based on two-dimensional gamma function.cpp C++复现了《基于二维伽马函数的光照不均匀图像自适应校正算法》这篇论文,对光照不均匀的图像有较好的校正效果,且不会像Retiex那样出现光晕。原理请看:https://blog.csdn.net/just_sort/article/details/88569129
2929
- Real-time adaptive contrast enhancement for imaging sensors.cpp C++复现了《Real-time adaptive contrast enhancement for imaging sensors》这篇论文,实时自适应局部对比度增强算法。原理请看:https://blog.csdn.net/just_sort/article/details/85208124
30+
- AutomaticWhiteBalanceMethod.cpp C++复现了《A Novel Automatic White Balance Method For Digital Still Cameras》这篇论文,实现了效果比完美反射更好得白平衡效果。原理请看:https://blog.csdn.net/just_sort/article/details/89183909
31+

0 commit comments

Comments
 (0)