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

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

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

 

 

下面是实现代码

 

 

#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),  8 ,  3 );
67      IplImage  * redCh  =  cvCreateImage(cvGetSize(srcImg),  8 ,  1 );
68      IplImage  * greenCh  =  cvCreateImage(cvGetSize(srcImg),  8 ,  1 );
69      IplImage  * blueCh  =  cvCreateImage(cvGetSize(srcImg),  8 ,  1 );
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  }