您的位置:首页 > Web前端

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

2019-05-14 14:43 10 查看

用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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: