opencv之颜色修正

该代码示例使用OpenCV库实现了局部颜色校正(LCC)算法,通过计算像素的BGR平均值进行预处理,然后应用高斯滤波。此外,还展示了像素值增加和对比度调整的方法,分别通过直接增加像素值和双边滤波后调整像素权重来实现。
摘要由CSDN通过智能技术生成

论文地址:IPOL Journal · Local Color Correction

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;


/* LCC 算法公式实现*/
Mat Color_correction(const Mat& src)
{
	int rows = src.rows;
	int cols = src.cols;
	//int** I;
	//I = new int* [rows];  // 在堆区开辟所有行的数组
	//for (int i = 0; i < rows; i++)
	//{
	//	I[i] = new int [cols];   // 在堆区开辟,所有列放到每一行中
	//}
	Mat I(src.size(), CV_8UC1);

	Mat mast(rows, cols, CV_8UC1);
	for (int i = 0; i < rows; i++)
	{
		uchar* data = mast.ptr<uchar>(i);  // 获取mast每行的地址
		for (int j = 0; j < cols; j++)
		{
			//I[i][j] = (src.at<Vec3b>(i, j)[0] + src.at<Vec3b>(i, j)[1] + src.at<Vec3b>(i, j)[2]) / 3.0;  // 将原图中每个像素点的 b+g+r的平均值存入I中
			I.at<uchar>(i,j) = (src.at<Vec3b>(i, j)[0] + src.at<Vec3b>(i, j)[1] + src.at<Vec3b>(i, j)[2]) / 3.0;
			//*data = 255 - I[i][j]; 
			*data = 255 - I.at<uchar>(i, j);
			data++;
		}
	}

	GaussianBlur(mast, mast, Size(41, 41), BORDER_DEFAULT);  // 高斯滤波
	Mat dst(rows, cols, CV_8UC3);
	for (int i = 0; i < rows; i++)
	{
		uchar* data = mast.ptr<uchar>(i);  
		for (int j = 0; j < cols; j++)
		{
			for (int k = 0; k < 3; k++)
			{
				float exp = pow(2, (128 - data[j]) / 128.0);
				int value = int(255 * pow(src.at<Vec3b>(i, j)[k] / 255.0, exp));
				dst.at<Vec3b>(i, j)[k] = value;
			}
		}
	}
	return dst;
}

// 单纯的增加像素值
Mat add_piexl(Mat src, int num)
{
	int rows = src.rows;
	int cols = src.cols;
	Mat dst(rows,cols,CV_8UC3);
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			dst.at<Vec3b>(i,j)[0] = src.at<Vec3b>(i, j)[0];
			dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1];
			dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2] + num;
		}
	}
	return dst;
}

Mat contrastimagecorrection(Mat src)
{
	int rows = src.rows;
	int cols = src.cols;
	Mat yuvimg;
	cvtColor(src, yuvimg, COLOR_BGR2YUV_I420);
	vector <Mat> mv;
	split(yuvimg, mv);
	Mat oldy = mv[0].clone();
	//for (int i = 0; i < rows; i++)
	//{
	//	for (int j = 0; j < cols; j++)
	//	{
	//		mv[0].at<uchar>(i, j) = 255 - mv[0].at<uchar>(i, j);
	//	}
	//}
	Mat temp;
	bilateralFilter(mv[0], temp, 9, 50, 50);  // 双边滤波
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			float exp = pow(2, (128 - (255 - temp.at<uchar>(i, j))) / 128.0);
			int value = int(255 * pow(oldy.at<uchar>(i, j) / 255.0, exp));
			temp.at<uchar>(i, j) = value;
		}
	}
	Mat dst(rows, cols, CV_8UC3);
	//mv[0] = temp;
	//merge(mv, dst);
	//cvtColor(dst, dst, COLOR_YUV2BGRA_I420);
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			if (oldy.at<uchar>(i, j) == 0)
			{
				for (int k = 0; k < 3; k++) dst.at<Vec3b>(i, j)[k] = 0;
			}
			else
			{
				dst.at<Vec3b>(i, j)[0] = (temp.at<uchar>(i, j) * (src.at<Vec3b>(i, j)[0] + oldy.at<uchar>(i, j)) / oldy.at<uchar>(i, j) + src.at<Vec3b>(i, j)[0] - oldy.at<uchar>(i, j)) >> 1;
				dst.at<Vec3b>(i, j)[1] = (temp.at<uchar>(i, j) * (src.at<Vec3b>(i, j)[1] + oldy.at<uchar>(i, j)) / oldy.at<uchar>(i, j) + src.at<Vec3b>(i, j)[1] - oldy.at<uchar>(i, j)) >> 1;
				dst.at<Vec3b>(i, j)[2] = (temp.at<uchar>(i, j) * (src.at<Vec3b>(i, j)[2] + oldy.at<uchar>(i, j)) / oldy.at<uchar>(i, j) + src.at<Vec3b>(i, j)[2] - oldy.at<uchar>(i, j)) >> 1;
			}
		}
	}
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			for (int k = 0; k < 3; k++)
			{
				if (dst.at<Vec3b>(i, j)[k] < 0)
				{
					dst.at<Vec3b>(i, j)[k] = 0;
				}
				else if (dst.at<Vec3b>(i, j)[k] > 255)
				{
					dst.at<Vec3b>(i, j)[k] = 255;
				}
			}
		}
	}
	return dst;
}

int main()
{
	Mat src = imread("E:/work/images/2010_005754.jpg");  // 2010_005754  2009_002774
	// LCC  论文地址为:http://www.ipol.im/pub/art/2011/gl_lcc/
	// 方式1
	Mat dst = Color_correction(src);
    // 方式2
	Mat dst1 = add_piexl(src, 100);

	// 方式3
	Rect rect(0, 0, (src.cols - 1) / 2 * 2, (src.rows - 1) / 2 * 2);
	Mat newsrc = src(rect);
	Mat dst2 = contrastimagecorrection(newsrc);
	imshow("origin", src);
	imshow("result", dst);
	imshow("result1", dst1);
	imshow("result2", dst2);
	char key = waitKey();
	if (key == 'q')
	{
		return 0;
	}
	return 0;
}

输入输出结果:

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值