用grayworld﹑perfetReflection﹑dynamicThreshold实现图像白平衡

用grayworld﹑perfetReflection﹑dynamicThreshold实现图像白平衡


感谢壮壮大佬!

1.grayworld

#include<opencv2\opencv.hpp>
#include<vector>
#include<iostream>
using namespace std;
using namespace cv;
Mat grayWorld(Mat srcImage)
{
	Mat disImage;
	vector<Mat>RGBImage;
	split(srcImage, RGBImage);
	//求原始图像RGB分量的均值
	double B = mean(RGBImage[0])[0];
	double G = mean(RGBImage[1])[0];
	double R = mean(RGBImage[2])[0];
	//调整RGB分量的增益
	double KB = (R + G + B) / (3 * B);
	double KG = (R + G + B) / (3 * G);
	double KR = (R + G + B) / (3 * R);
	//调整RGB三个通道各自的值
	RGBImage[0] = (RGBImage[0] * KB);
	RGBImage[1] = (RGBImage[1] * KG);
	RGBImage[2] = RGBImage[2] * KR;
	//RGB三个图像合并
	merge(RGBImage, disImage);
	return disImage;
}
int main(int argc, char**argv)
{
	Mat srcImage = imread("grayWorld.png");
	if (srcImage.empty())
	{
		printf("could not load srcImage.....\n");
		return -1;
	}
	namedWindow("srcImage", CV_WINDOW_AUTOSIZE);
	imshow("srcImage", srcImage);
	Mat dstImage = grayWorld(srcImage);
	if (dstImage.empty())
	{
		printf("could not load dstImage.....\n");
		return -1;
	}
	imshow("灰度世界法", dstImage);
	waitKey(0);
	return 0;
}

2.perfetReflection

在这里插入图片描述

#include<opencv2\opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int Threshold;
int Ratio = 20;
int Matvalue = 255;

void perfectReflection(Mat sourceImage)
{
	//计算每个像素的R,G,B之和
	int HistRGB[768] = { 0 };
	int sumRGB;
	for (int i = 0; i < sourceImage.rows; i++)
	{
		for (int j = 0; j < sourceImage.cols; j++)
		{
			sumRGB = sourceImage.at<Vec3b>(i, j)[0] + sourceImage.at<Vec3b>(i, j)[1] + sourceImage.at<Vec3b>(i, j)[2];
			HistRGB[sumRGB]++;
		}
	}
	int sum = 0;
	//按R+B+G值的大小计算出Ratio的白色参考点的阈值
	for (sumRGB = 767; sumRGB >= 0; sumRGB--)
	{
		sum += HistRGB[sumRGB];
		if (sum > sourceImage.rows*sourceImage.cols*Ratio / 100)
		{
			Threshold = sumRGB;
			break;
		}
	}
	//遍历图像中的每个点,计算其中R+G+B值大于T的所有点的R,G,B分量的累积和的平均值
	int averB = 0;
	int averG = 0;
	int averR = 0;
	int count = 0;
	for (int i = 0; i < sourceImage.rows; i++)
	for (int j = 0; j < sourceImage.cols; j++)
	{
		if (sourceImage.at<Vec3b>(i, j)[0] + sourceImage.at<Vec3b>(i, j)[1] + sourceImage.at<Vec3b>(i, j)[2]>Threshold)
		{
			averB += sourceImage.at<Vec3b>(i, j)[0];
			averG += sourceImage.at<Vec3b>(i, j)[1];
			averR += sourceImage.at<Vec3b>(i, j)[2];
			count++;
		}
	}
	averB = averB / count;
	averG = averG / count;
	averR = averR / count;
	//对每个点的像素量化到[0,255]之间
	for (int i = 0; i < sourceImage.rows; i++)
	{
		for (int j = 0; j < sourceImage.cols; j++)
		{
			sourceImage.at<Vec3b>(i, j)[0] = saturate_cast<uchar>(sourceImage.at<Vec3b>(i, j)[0] * Matvalue / averB);
			sourceImage.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(sourceImage.at<Vec3b>(i, j)[1] * Matvalue / averG);
			sourceImage.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(sourceImage.at<Vec3b>(i, j)[2] * Matvalue / averR);
		}
	}
}
int main(int argc, char**argv)
{
	Mat srcImage = imread("bmg.png");

//	namedWindow("srcImage", CV_WINDOW_AUTOSIZE);
	imshow("原始图片", srcImage);
	if (srcImage.empty())
	{
		printf("could not load srcImage.....\n");
		return -1;
	}
	perfectReflection(srcImage);
	imshow("完美反射法后", srcImage);

	waitKey(0);
	return 0;
}

3.dynamicThreshold

在这里插入图片描述

#include<opencv2\opencv.hpp>
#include<vector>
#include<iostream>
using namespace std;
using namespace cv;
int row = 1;
int col = 1;//此处把图片分成1块
double baidianave(Mat frame, int irow, int lclo)
{
	int width_step = frame.cols / col;
	int height_step = frame.rows / row;
	int a[256] = { 0 };
	double sum = 0;
	double sum1 = 0;
	double ave;
	for (int rows = irow*height_step; rows < (irow + 1)*height_step; rows++)
	{
		for (int clos = lclo*width_step; clos < (lclo + 1)*width_step; clos++)
		{
			int d = frame.at<uchar>(rows, clos);
			a[d]++;
		}
	}
	int value = 255;
	for (int k = 255; k>0; k--)
	{
		sum1 += a[k];
		if (sum1 > width_step*height_step / 10)
			break;
		value--;
	}
	sum = 0;
	for (int i = value; i < 256; i++)
		sum += a[i] * i;
	ave = sum / sum1;
	return ave;
}
double baidianave(Mat frame, int n)
{
	int a[256] = { 0 };
	double sum = 0;
	double sum1 = 0;
	double ave;
	for (int i = 0; i < n; i++)
	{
		int d = frame.at<double>(0, i);
		a[d]++;
	}
	int value = 255;
	for (int k = 255; k>0; k--)
	{
		sum1 += a[k];
		if (sum1 >(n / 20))
			break;
		value--;
	}
	sum = 0;
	for (int i = value; i < 256; i++)
		sum += a[i] * i;
	ave = sum / sum1;
	//cout << ave << endl;
	return ave;
}
int main()
{
	Mat srcImage = imread("bmg.png");
	//if (srcImage.empty())
	//{
	//	printf("could not load srcImage.....\n");
	//	return -1;
	//}
	imshow("原图", srcImage);
	vector<Mat>YCrCbImage;
	Mat Yimage(srcImage.size(), CV_8UC1), Crimage(srcImage.size(), CV_8UC1), Cbimage(srcImage.size(), CV_8UC1), Image;
	cvtColor(srcImage, Image, CV_RGB2YCrCb);
	split(Image, YCrCbImage);
	Yimage = YCrCbImage[0];
	Crimage = YCrCbImage[1];
	Cbimage = YCrCbImage[2];
	//计算每个分块的高度和宽度
	int width_step = srcImage.cols / col;
	int height_step = srcImage.rows / row;
	//分别对每一个图像分块进行处理
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			int count = 0;
			//计算每部分Cb,Cr的均值和方差
			double Mb = 0, Db = 0, b = 0;
			double Mr = 0, Dr = 0, r = 0;
			//求取Cb,Cr的平均值Mb,Mr
			for (int rows = i*height_step; rows < (i + 1)*height_step; rows++)
			{
				for (int clos = j*width_step; clos < (j + 1)*width_step; clos++)
				{
					Mb += Cbimage.at<uchar>(rows, clos);
					Mr += Crimage.at<uchar>(rows, clos);
					count++;
				}
			}
			Mb /= count;
			Mr /= count;
			//求取Cb,Cr分量的绝对差的累积值Db,Dr
			for (int rows = i*height_step; rows < (i + 1)*height_step; rows++)
			{
				for (int clos = j*width_step; clos < (j + 1)*width_step; clos++)
				{
					Db += abs(Cbimage.at<uchar>(rows, clos) - Mb);
					Dr += abs(Crimage.at<uchar>(rows, clos) - Mr);
				}
			}
			Db /= count;
			Dr /= count;
			if (Mb < 0)
				b = Mb + (-1)*Db;
			else
				b = Mb + Db;
			if (Mr < 0)
				r = 1.5 * Mr + Dr*(-1);
			else
				r = 1.5 *Mr + Dr;
			double Ymax = baidianave(YCrCbImage[0], i, j);
			Mat Bbaidian(1, 600000, CV_64FC1);
			Mat Gbaidian(1, 600000, CV_64FC1);
			Mat Rbaidian(1, 600000, CV_64FC1);
			int n1 = 0;
			//进行白点选择
			for (int rows = i*height_step; rows < (i + 1)*height_step; rows++)
			{
				for (int clos = j*width_step; clos < (j + 1)*width_step; clos++)
				{
					if ((Cbimage.at<uchar>(rows, clos) - b) < 1.5*Db &&(Crimage.at<uchar>(rows, clos) - r) < 1.5*Dr)
					{
						double d1 = srcImage.at<Vec3b>(rows, clos)[0];
						Bbaidian.at<double>(0, n1) = d1;
						double d2 = srcImage.at<Vec3b>(rows, clos)[1];
						Gbaidian.at<double>(0, n1) = d2;
						double d3 = srcImage.at<Vec3b>(rows, clos)[2];
						Rbaidian.at<double>(0, n1) = d3;
						n1++;
					}
				}
			}
			//计算白色参考点亮度值的平均值Rave,Gave,Bave
			double Bave = baidianave(Bbaidian, n1);
			double Gave = baidianave(Gbaidian, n1);
			double Rave = baidianave(Rbaidian, n1);

			cout << "Bave" << Bave << "  " << "Gave" << Gave << "   " << "Rave" << Rave << endl;
			double Bgain = Ymax / (Bave);
			double Ggain = Ymax / (Gave);
			double Rgain = Ymax / (Rave);

			//cout << i << endl;
			for (int rows = i*height_step; rows < (i + 1)*height_step; rows++)
			{
				for (int clos = j*width_step; clos < (j + 1)*width_step; clos++)
				{
					srcImage.at<Vec3b>(rows, clos)[0] = saturate_cast<uchar>(srcImage.at<Vec3b>(rows, clos)[0] * Bgain);
					srcImage.at<Vec3b>(rows, clos)[1] = saturate_cast<uchar>(srcImage.at<Vec3b>(rows, clos)[1] * Ggain);
					srcImage.at<Vec3b>(rows, clos)[2] = saturate_cast<uchar>(srcImage.at<Vec3b>(rows, clos)[2] * Rgain);
				}
			}
		}
	}
//	cout << srcImage.at<Vec3b>(10, 300) << endl;
	imshow("动态阈值法后", srcImage);
	waitKey(0);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值