很久之前看过一篇关于色彩平衡文章,在该文章中介绍了一种非常简单高效的

色彩平衡算法。下图是算法的演示效果(左边为处理后的图像,右边为处理前的图像)。

从图中可以看出算法有效的改善的图像的色彩,使得色彩更加的真实。

 

下面是实现代码

#include "stdafx.h"

#include "cv.h"
#include "cxcore.h"
#include "highgui.h"

#pragma comment(lib, "cv.lib")
#pragma comment(lib, "cxcore.lib")
#pragma comment(lib, "highgui.lib")

void color_balance(IplImage *img)
{
int histo[256] = {0};
int num_of_pixels = img->width*img->height;
for(int y = 0; y < img->height; ++y)
{
uchar *data = (uchar*)(img->imageData + y*img->widthStep);
for(int x = 0; x < img->width; ++x)
{
histo[data[x]] += 1;
}
}

for(int i = 1; i < 256; ++i)
histo[i] = histo[i] + histo[i-1];

double s = 0.1;
int vmin = 0;
while (histo[vmin + 1] <= cvRound(num_of_pixels*s/2))
vmin = vmin + 1;
int vmax = 255 - 1;
while( histo[vmax - 1] > cvRound(num_of_pixels*(1 - s/2)))
{
vmax = vmax - 1;
}
if (vmax < 255 - 1)
vmax = vmax + 1;

for(int y = 0; y < img->height; ++y)
{

uchar *data = (uchar*)(img->imageData + y*img->widthStep);
for(int x = 0; x < img->width; ++x)
{
if(data[x] < vmin)
data[x] = vmin;
if(data[x] > vmax)
data[x] = vmax;
}
}

for(int y = 0; y < img->height; ++y)
{

uchar *data = (uchar*)(img->imageData + y*img->widthStep);
for(int x = 0; x < img->width; ++x)
{
data[x] = cvRound((data[x] - vmin)*255.0/(vmax - vmin));
}
}

}
int _tmain(int argc, _TCHAR* argv[])
{
IplImage *srcImg = cvLoadImage("D:\\colorbalance.jpg");
IplImage *dstImg = cvCreateImage(cvGetSize(srcImg), 8, 3);
IplImage *redCh = cvCreateImage(cvGetSize(srcImg), 8, 1);
IplImage *greenCh = cvCreateImage(cvGetSize(srcImg), 8, 1);
IplImage *blueCh = cvCreateImage(cvGetSize(srcImg), 8, 1);
cvSplit(srcImg, blueCh, greenCh, redCh, NULL);
color_balance(redCh);
color_balance(greenCh);
color_balance(blueCh);
cvMerge(blueCh, greenCh, redCh, NULL, dstImg);

cvNamedWindow("src", CV_WINDOW_AUTOSIZE);
cvShowImage("src", srcImg);

cvNamedWindow("dst", CV_WINDOW_AUTOSIZE);
cvShowImage("dst", dstImg);
cvWaitKey(0);

return 0;
}

 1 #include "stdafx.h"
 2 
 3 #include "cv.h"
 4 #include "cxcore.h"
 5 #include "highgui.h"
 6 
 7 #pragma comment(lib, "cv.lib")
 8 #pragma comment(lib, "cxcore.lib")
 9 #pragma comment(lib, "highgui.lib")
10 
11 void color_balance(IplImage *img)
12 {
13     int histo[256= {0};
14     int num_of_pixels = img->width*img->height;
15     for(int y = 0; y < img->height; ++y)
16     {
17             uchar *data = (uchar*)(img->imageData +  y*img->widthStep);
18         for(int x = 0; x < img->width; ++x)
19         {
20             histo[data[x]] += 1;
21         }
22     }
23 
24     for(int i = 1; i < 256++i)
25         histo[i] = histo[i] + histo[i-1];
26 
27     double s = 0.1;
28     int vmin = 0;
29     while (histo[vmin + 1<= cvRound(num_of_pixels*s/2))
30         vmin = vmin + 1;
31     int vmax = 255 - 1;
32     while( histo[vmax - 1> cvRound(num_of_pixels*(1 - s/2)))
33     {
34         vmax = vmax - 1;
35     }
36     if (vmax < 255 - 1)
37         vmax = vmax + 1;
38 
39     for(int y = 0; y < img->height; ++y)
40     {
41 
42         uchar *data = (uchar*)(img->imageData +  y*img->widthStep);
43         for(int x = 0; x < img->width; ++x)
44         {
45             if(data[x] < vmin)
46                 data[x] = vmin;
47             if(data[x] > vmax)
48                 data[x] = vmax;
49         }
50     }
51 
52     for(int y = 0; y < img->height; ++y)
53     {
54 
55         uchar *data = (uchar*)(img->imageData +  y*img->widthStep);
56         for(int x = 0; x < img->width; ++x)
57         {
58             data[x] = cvRound((data[x] - vmin)*255.0/(vmax - vmin));
59         }
60     }
61 
62 }
63 int _tmain(int argc, _TCHAR* argv[])
64 {
65     IplImage *srcImg = cvLoadImage("D:\\colorbalance.jpg");
66     IplImage *dstImg = cvCreateImage(cvGetSize(srcImg), 83);
67     IplImage *redCh = cvCreateImage(cvGetSize(srcImg), 81);
68     IplImage *greenCh = cvCreateImage(cvGetSize(srcImg), 81);
69     IplImage *blueCh = cvCreateImage(cvGetSize(srcImg), 81);
70     cvSplit(srcImg, blueCh, greenCh, redCh, NULL);
71     color_balance(redCh);
72     color_balance(greenCh);
73     color_balance(blueCh);
74     cvMerge(blueCh, greenCh, redCh, NULL, dstImg);
75 
76     cvNamedWindow("src", CV_WINDOW_AUTOSIZE);
77     cvShowImage("src", srcImg);
78 
79     cvNamedWindow("dst", CV_WINDOW_AUTOSIZE);
80     cvShowImage("dst", dstImg);
81     cvWaitKey(0);
82 
83     return 0;
84 }