一、概念
什么是白平衡呢?白平衡就是針對不同色溫條件下,通過調整攝像機內部的色彩電路使拍攝出來的影像抵消偏色,更接近人眼的視覺習慣。白平衡可以簡單地理解為在任意色溫條件下,攝像機鏡頭所拍攝的標準白色經過電路的調整,使之成像后仍然為白色。這是一種經常出現的情況,但不是全部,白平衡其實是通過攝像機內部的電路調整(改變藍、綠、紅三個CCD電平的平衡關系)使反射到鏡頭里的光線都呈現為消色。
通俗的來說就是:是圖片中最亮的部分為白色,最暗的部分為黑色。其余部分進行拉伸。效果如下:
原圖:
?
robust color balance:
?
簡單的說就是:在rgb三通道上分別統計每個像素值的出現次數。將1%的最大值和最小值設置為255和0。其余值映射到(0,255),這樣使得每個值通道的值在rgb中分布較均勻。達到顏色平衡的結果。。
opencv實現了簡單白平衡。使用多層直方圖,比單個直方圖的優點,應該是速度更快。實際上并不一定要這么實現。且算法的實現應該有問題。以下是修改后代碼,中文部分是我加的注釋。主要加入offset來標識每層的偏移量。opencv結果:
?
? ? ? ?
? ? ? ? /*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是通道下標, src[0], src[1], src[3]分別表示三個通道
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();
//對該通道內每個像素進行處理
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;
//基本上等同于對每個元素進行統計
//這種雙層hist的方法實際是有問題的。這種方法設計來對加速,0,16作為一個統計階段統計,而后面的每個像素則是具體的次數
//例如一個像素3,則可能使得hist[0],hist[3]各增加一次。hist[0]是對的,但是hist[3]的意義就變了。
//之所以程序寫這么麻煩的原因是,輸入min,max,輸出min,max都有可能變化。
//改正方法應該是對后面的層數加偏移操作。保證正確性。
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、灰度世界算法
灰度世界算法以灰度世界假設為基礎,該假設認為:對于一幅有著大量色彩變化的圖像,R、G、B,三個分量的平均值趨于同一灰度值。從物理意義上講,灰色世界法假設自然界景物對于光線的平均反射的均值在總體上是個定值Gray,這個定值近似地為“灰色”。顏色平衡算法將這一假設強制應用于待處理圖像,可以從圖像中消除環境光的影響,獲得原始場景圖像。
算法執行步驟:
(1)確定灰度均值:Gray
(2)計算三個通道的增益:Kr,Kg,Kb;
(3)調整R、G、B分量;
這種算法簡單快速,但是當圖像場景顏色并不豐富時,尤其出現大塊單色物體時,該算法常會失效。
以下是OpenCV實現的灰度世界算法代碼:
#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];
//需要調整的RGB分量的增益
double KR, KG, KB;
KB = (R + G + B) / (3 * B);
KG = (R + G + B) / (3 * G);
KR = (R + G + B) / (3 * R);
//調整RGB三個通道各自的值
imageRGB[0] = imageRGB[0] * KB;
imageRGB[1] = imageRGB[1] * KG;
imageRGB[2] = imageRGB[2] * KR;
//RGB三通道圖像合并
merge(imageRGB, imageSource);
imshow(“白平衡調整后”, imageSource);
waitKey();
return 0;
}
原始圖像一,整體圖像偏綠色:
?
白平衡校正后,天空的藍色和樹葉的綠色都得到了很好的還原:
?
原始圖像二,整體偏黃色:
?
白平衡校正后效果:
?
2、完美全反射理論
完美全反射理論(perfect Reflector)假設圖像上最亮點就是白點,并以此白點為參考對圖像進行自動白平衡,最亮點定義為R+G+B的最大值。
3、動態閾值算法
參考論文:A Novel Automatic White Balance Method For Digital Still Cameras
算法分為兩個步驟:白點檢測和白點調整。
三、驗證
通過測試效果表明:動態閾值法,1、該算法效果非常好;2、對塊大小不太敏感,因此非常適合于自動化操作。
評論
查看更多