一、概念
什么是白平衡呢?白平衡就是針對(duì)不同色溫條件下,通過調(diào)整攝像機(jī)內(nèi)部的色彩電路使拍攝出來的影像抵消偏色,更接近人眼的視覺習(xí)慣。白平衡可以簡(jiǎn)單地理解為在任意色溫條件下,攝像機(jī)鏡頭所拍攝的標(biāo)準(zhǔn)白色經(jīng)過電路的調(diào)整,使之成像后仍然為白色。這是一種經(jīng)常出現(xiàn)的情況,但不是全部,白平衡其實(shí)是通過攝像機(jī)內(nèi)部的電路調(diào)整(改變藍(lán)、綠、紅三個(gè)CCD電平的平衡關(guān)系)使反射到鏡頭里的光線都呈現(xiàn)為消色。
通俗的來說就是:是圖片中最亮的部分為白色,最暗的部分為黑色。其余部分進(jìn)行拉伸。效果如下:
原圖:
?
robust color balance:
?
簡(jiǎn)單的說就是:在rgb三通道上分別統(tǒng)計(jì)每個(gè)像素值的出現(xiàn)次數(shù)。將1%的最大值和最小值設(shè)置為255和0。其余值映射到(0,255),這樣使得每個(gè)值通道的值在rgb中分布較均勻。達(dá)到顏色平衡的結(jié)果。。
opencv實(shí)現(xiàn)了簡(jiǎn)單白平衡。使用多層直方圖,比單個(gè)直方圖的優(yōu)點(diǎn),應(yīng)該是速度更快。實(shí)際上并不一定要這么實(shí)現(xiàn)。且算法的實(shí)現(xiàn)應(yīng)該有問題。以下是修改后代碼,中文部分是我加的注釋。主要加入offset來標(biāo)識(shí)每層的偏移量。opencv結(jié)果:
?
? ? ? ?
? ? ? ? /*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// * Redistribution‘s of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution’s in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors “as is” and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include 《vector》
#include 《algorithm》
#include 《iterator》
#include 《iostream》
#include “xphoto.hpp”
#include “opencv2/imgproc.hpp”
#include “opencv2/core.hpp”
#include “opencv2/core/core_c.h”
#include “opencv2/core/types.hpp”
#include “opencv2/core/types_c.h”
#define USE_OFFSET 1
namespace cv
{
namespace xphoto
{
template 《typename T》
void balanceWhite(std::vector 《 Mat_《T》 》 &src, Mat &dst,
const float inputMin, const float inputMax,
const float outputMin, const float outputMax, const int algorithmType)
{
switch ( algorithmType )
{
case WHITE_BALANCE_SIMPLE:
{
/********************* Simple white balance *********************/
float s1 = 2.0f; // low quantile
float s2 = 2.0f; // high quantile
int depth = 2; // depth of histogram tree
if (src[0].depth() != CV_8U)
++depth;
int bins = 16; // number of bins at each histogram level
int nElements = int( pow(bins, depth) );
// number of elements in histogram tree
//i是通道下標(biāo), src[0], src[1], src[3]分別表示三個(gè)通道
for (size_t i = 0; i 《 src.size(); ++i)
{
std::vector 《int》 hist(2 * nElements, 0);
typename Mat_《T》::iterator beginIt = src[i].begin();
typename Mat_《T》::iterator endIt = src[i].end();
//對(duì)該通道內(nèi)每個(gè)像素進(jìn)行處理
for (typename Mat_《T》::iterator it = beginIt; it != endIt; ++it)
// histogram filling
{
int pos = 0;
float minValue = inputMin - 0.5f;
float maxValue = inputMax + 0.5f;
T val = *it;
float interval = float(maxValue - minValue) / bins;
//基本上等同于對(duì)每個(gè)元素進(jìn)行統(tǒng)計(jì)
//這種雙層hist的方法實(shí)際是有問題的。這種方法設(shè)計(jì)來對(duì)加速,0,16作為一個(gè)統(tǒng)計(jì)階段統(tǒng)計(jì),而后面的每個(gè)像素則是具體的次數(shù)
//例如一個(gè)像素3,則可能使得hist[0],hist[3]各增加一次。hist[0]是對(duì)的,但是hist[3]的意義就變了。
//之所以程序?qū)戇@么麻煩的原因是,輸入min,max,輸出min,max都有可能變化。
//改正方法應(yīng)該是對(duì)后面的層數(shù)加偏移操作。保證正確性。
int offset = 0;
for (int j = 0; j 《 depth; ++j)
{
int currentBin = int( (val - minValue + 1e-4f) / interval );
++hist[pos + currentBin];
#if USE_OFFSET
offset = offset + (int)pow(bins, j);
#endif
pos = (offset + pos + currentBin)*bins;
minValue = minValue + currentBin*interval;
// maxValue = minValue + interval; //多余語句
interval /= bins;
}
}
int total = int( src[i].total() );
int p1 = 0, p2 = bins - 1;
int n1 = 0, n2 = total;
float minValue = inputMin - 0.5f;
float maxValue = inputMax + 0.5f;
float interval = (maxValue - minValue) / float(bins);
int offset = 0;
for (int j = 0; j 《 depth; ++j)
// searching for s1 and s2
{
while (n1 + hist[p1] 《 s1 * total / 100.0f)
{
n1 += hist[p1++];
minValue += interval;
}
#if USE_OFFSET
offset = offset + int(pow(bins, j));
#endif
std::cout 《《 offset 《《 std::endl;
p1 *= bins;
p1 = p1 + offset;
while (n2 - hist[p2] 》 (100.0f - s2) * total / 100.0f)
{
n2 -= hist[p2--];
maxValue -= interval;
}
p2 = p2*bins - 1;
p2 = p2 + offset;
interval /= bins;
}
src[i] = (outputMax - outputMin) * (src[i] - minValue)
/ (maxValue - minValue) + outputMin;
}
/****************************************************************/
break;
}
default:
CV_Error_( CV_StsNotImplemented,
(“Unsupported algorithm type (=%d)”, algorithmType) );
}
dst.create(/**/ src[0].size(), CV_MAKETYPE( src[0].depth(), int( src.size() ) ) /**/);
cv::merge(src, dst);
}
二、方法
1、灰度世界算法
灰度世界算法以灰度世界假設(shè)為基礎(chǔ),該假設(shè)認(rèn)為:對(duì)于一幅有著大量色彩變化的圖像,R、G、B,三個(gè)分量的平均值趨于同一灰度值。從物理意義上講,灰色世界法假設(shè)自然界景物對(duì)于光線的平均反射的均值在總體上是個(gè)定值Gray,這個(gè)定值近似地為“灰色”。顏色平衡算法將這一假設(shè)強(qiáng)制應(yīng)用于待處理圖像,可以從圖像中消除環(huán)境光的影響,獲得原始場(chǎng)景圖像。
算法執(zhí)行步驟:
(1)確定灰度均值:Gray
(2)計(jì)算三個(gè)通道的增益:Kr,Kg,Kb;
(3)調(diào)整R、G、B分量;
這種算法簡(jiǎn)單快速,但是當(dāng)圖像場(chǎng)景顏色并不豐富時(shí),尤其出現(xiàn)大塊單色物體時(shí),該算法常會(huì)失效。
以下是OpenCV實(shí)現(xiàn)的灰度世界算法代碼:
#include 《highgui/highgui.hpp》
#include 《imgproc/imgproc.hpp》
using namespace cv;
int main()
{
Mat imageSource = imread(“02.jpg”);
imshow(“原始圖像”, imageSource);
vector《Mat》 imageRGB;
//RGB三通道分離
split(imageSource, imageRGB);
//求原始圖像的RGB分量的均值
double R, G, B;
B = mean(imageRGB[0])[0];
G = mean(imageRGB[1])[0];
R = mean(imageRGB[2])[0];
//需要調(diào)整的RGB分量的增益
double KR, KG, KB;
KB = (R + G + B) / (3 * B);
KG = (R + G + B) / (3 * G);
KR = (R + G + B) / (3 * R);
//調(diào)整RGB三個(gè)通道各自的值
imageRGB[0] = imageRGB[0] * KB;
imageRGB[1] = imageRGB[1] * KG;
imageRGB[2] = imageRGB[2] * KR;
//RGB三通道圖像合并
merge(imageRGB, imageSource);
imshow(“白平衡調(diào)整后”, imageSource);
waitKey();
return 0;
}
原始圖像一,整體圖像偏綠色:
?
白平衡校正后,天空的藍(lán)色和樹葉的綠色都得到了很好的還原:
?
原始圖像二,整體偏黃色:
?
白平衡校正后效果:
?
2、完美全反射理論
完美全反射理論(perfect Reflector)假設(shè)圖像上最亮點(diǎn)就是白點(diǎn),并以此白點(diǎn)為參考對(duì)圖像進(jìn)行自動(dòng)白平衡,最亮點(diǎn)定義為R+G+B的最大值。
3、動(dòng)態(tài)閾值算法
參考論文:A Novel Automatic White Balance Method For Digital Still Cameras
算法分為兩個(gè)步驟:白點(diǎn)檢測(cè)和白點(diǎn)調(diào)整。
三、驗(yàn)證
通過測(cè)試效果表明:動(dòng)態(tài)閾值法,1、該算法效果非常好;2、對(duì)塊大小不太敏感,因此非常適合于自動(dòng)化操作。
評(píng)論
查看更多