白平衡算法

常用的几种白平衡算法,可参考白平衡(灰度世界、全反射、色温估计)以及白平衡算法实现。下文代码参考一种简单的图像白平衡计算方法。

感谢以上三位博主的分享。

算法(看起来应该是全反射算法)核心思想:在rgb三通道上分别计算直方图,然后将1%的最大值和最小值设置为255和0,其余值映射到(0, 255)区间内,这样使得每个通道的值均匀分布,以实现简单的颜色平衡。实际测试对偏色比较厉害的图像效果较好。

代码实现如下:

#include 
#include 

cv::Mat cwb(cv::Mat mat, float min_ratio,float max_ratio)
{
	const float inputMin = 0.0f;
	const float inputMax = 255.0f;
	const float outputMin = 0.0f;
	const float outputMax = 255.0f; 

	std::vector bgr;
	split(mat, bgr);        //分离B、G、R三通道

							// 在rgb三通道上分别计算直方图
							// 将1%的最大值和最小值设置为255和0
							// 其余值映射到(0, 255), 这样使得每个通道的值在rgb中分布较均匀, 以实现简单的颜色平衡
							/********************* Simple white balance *********************/
	float s1 = min_ratio;  //最低值百分比
	float s2 = max_ratio;  //最高值百分比

	int depth = 2;  // depth of histogram tree
	int bins = 16;  // number of bins at each histogram level
	int total = bgr[0].cols * bgr[0].rows;
	int nElements = int(pow((float)bins, (float)depth)); // number of elements in histogram tree

	for (size_t k = 0; k < bgr.size(); ++k)
	{
		std::vector hist(nElements, 0);
		uchar *pImg = bgr[k].data;
		// histogram filling
		for (int i = 0; i < total; i++)
		{
			int pos = 0;
			float minValue = inputMin - 0.5f;
			float maxValue = inputMax + 0.5f;
			float interval = float(maxValue - minValue) / bins;

			uchar val = pImg[i];
			for (int j = 0; j < depth; ++j)
			{
				int currentBin = int((val - minValue + 1e-4f) / interval);
				++hist[pos + currentBin];

				pos = (pos + currentBin)*bins;
				minValue = minValue + currentBin*interval;
				interval /= bins;
			}
		}

		int p1 = 0, p2 = bins - 1;
		int n1 = 0, n2 = total;
		float minValue = inputMin - 0.5f;
		float maxValue = inputMax + 0.5f;
		float interval = float(maxValue - minValue) / bins;

		// searching for s1 and s2
		for (int j = 0; j < depth; ++j)
		{
			while (n1 + hist[p1] < s1 * total / 100.0f)
			{
				n1 += hist[p1++];
				minValue += interval;
			}
			p1 *= bins;

			while (n2 - hist[p2] > (100.0f - s2) * total / 100.0f)
			{
				n2 -= hist[p2--];
				maxValue -= interval;
			}
			p2 = p2*bins - 1;

			interval /= bins;
		}

		bgr[k] = (outputMax - outputMin) * (bgr[k] - minValue) / (maxValue - minValue) + outputMin;
	}

	cv::merge(bgr, mat); //合并R、G、B三通道

	return mat;
}


int main(int argc, char** argv) {
	cv::Mat src,dst;
	src = cv::imread("D:/VS2015_Projects/opencv_workspace/img/cwb_test/m1.jpg");

	if(src.empty())
	{
		std::cout << "image load failed!" << std::endl;
		return -1;
	}

	resize(src, src, cv::Size(src.cols / 2, src.rows / 2));
	cv::imshow("input image", src);

	
	float min_ratio = 1.0f;  //最低值百分比:此处取1%(可根据情况测试调整比例,以获得更合适效果)
	float max_ratio = 1.0f;  //最高值百分比:此处取1%
	dst = cwb(src, min_ratio, max_ratio);
	cv::imshow("cwb 1%", dst);

	cv::waitKey(0);
	return 0;

}

效果如下:

白平衡算法_第1张图片
可看出,色彩校正效果还是不错的。

另外,经测试,该算法具有很好的去雾霾效果,如下:

白平衡算法_第2张图片

白平衡算法_第3张图片

你可能感兴趣的:(OPENCV)