实现函数代码:
1 /****************************************/
2 /* 实现自动对比度的函数 */
3 /* 目前只有前后中通道调用 */
4 /* 彩色的已经加入到了函数内部 */
5 /*****************************************/
6 void BrightnessAndContrastAuto(const cv::Mat &src, cv::Mat &dst, float clipHistPercent)
7 {
8 CV_Assert(clipHistPercent >= 0);
9 CV_Assert((src.type() == CV_8UC1) || (src.type() == CV_8UC3) || (src.type() == CV_8UC4));
10
11 int histSize = 256;
12 float alpha, beta;
13 double minGray = 0, maxGray = 0;
14
15 //to calculate grayscale histogram
16 cv::Mat gray;
17 if (src.type() == CV_8UC1) gray = src;
18 else if (src.type() == CV_8UC3) cvtColor(src, gray, CV_BGR2GRAY);
19 else if (src.type() == CV_8UC4) cvtColor(src, gray, CV_BGRA2GRAY);
20 if (clipHistPercent == 0)
21 {
22 // keep full available range
23 cv::minMaxLoc(gray, &minGray, &maxGray);
24 }
25 else
26 {
27 cv::Mat hist; //the grayscale histogram
28
29 float range[] = { 0, 256 };
30 const float* histRange = { range };
31 bool uniform = true;
32 bool accumulate = false;
33 cv::calcHist(&gray, 1, 0, cv::Mat (), hist, 1, &histSize, &histRange, uniform, accumulate);
34
35 // calculate cumulative distribution from the histogram
36 std::vector<float> accumulator(histSize);
37 accumulator[0] = hist.at<float>(0);
38 for (int i = 1; i < histSize; i++)
39 {
40 accumulator[i] = accumulator[i - 1] + hist.at<float>(i);
41 }
42
43 // locate points that cuts at required value
44 float max = accumulator.back();
45 clipHistPercent *= (max / 100.0); //make percent as absolute
46 clipHistPercent /= 2.0; // left and right wings
47 // locate left cut
48 minGray = 0;
49 while (accumulator[minGray] < clipHistPercent)
50 minGray++;
51
52 // locate right cut
53 maxGray = histSize - 1;
54 while (accumulator[maxGray] >= (max - clipHistPercent))
55 maxGray--;
56 }
57
58 // current range
59 float inputRange = maxGray - minGray;
60
61 alpha = (histSize - 1) / inputRange; // alpha expands current range to histsize range
62 beta = -minGray * alpha; // beta shifts current range so that minGray will go to 0
63
64 // Apply brightness and contrast normalization
65 // convertTo operates with saurate_cast
66 src.convertTo(dst, -1, alpha, beta);
67
68 // restore alpha channel from source
69 if (dst.type() == CV_8UC4)
70 {
71 int from_to[] = { 3, 3};
72 cv::mixChannels(&src, 4, &dst,1, from_to, 1);
73 }
74 return;
75 }