用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; }
相关文章推荐
- 基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果
- 【VS开发】【图像处理】相机中白平衡的算法模拟实现
- 【VS开发】【图像处理】基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果
- 图像白平衡原理及实现
- 基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果
- 基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果
- 基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果
- 图像基本处理算法的简单实现(二)
- 【转载】从零实现3D图像引擎:(2)画2D直线不简单
- 用OpenCV实现图像的水平镜像(翻转)变换和竖直镜像(翻转)变换(垂直镜像变换)的源码
- 使用Halcon实现图像处理
- 用C++ Builder实现图像的特技显示
- 图像配准实现(matlab篇)
- 解析C#彩色图像灰度化算法的实现代码详解
- 图像处理常用算法GPU实现一:图像二值化
- OpenCV下实现单窗口显示多幅图像的源码!
- 图像肤色初步检测实现
- [导入]jquery+.net实现类似开心网图像缩放截取功能(附代码下载)
- OpenCV实现在图像中写入汉字
- OpenCV实现对图像的光照归一化处理