图像颜色增强算法Opencv

本文介绍了一种基于GIMP Color-enhance插件的颜色增强算法,并详细解释了其实现过程。该算法通过对图像的HSV空间V值进行重新量化来提升图像色彩。文章还探讨了算法的局限性和可能的改进方向。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法来源于GIMP中的Color-enhance插件,主要思路就是对HSV空间的V值进行重新量化。其代码是开源的,但用起来不太方便,所以我用Opencv重新改写了一下。

一、算法主要步骤:

1.图像转换到CMY空间,每个像素点(三通道,包含C、M、Y三个值)各减去最小值,即C -=min(C,M,Y),M -=min(C,M,Y),Y -=min(C,M,Y)。

2.1中得到的图像转换到HSV空间。

3.计算V的极大极小值,重新量化V值:newPixel = oldPixel / 255- vMin) / (vMax - vMin)。

4.按原步骤,将图像转换回去,得到颜色增强的图像。

二、代码详解

环境:win10 x64,vs2013+OpenCV2.4.13

1.图像转换到CMY空间,每个像素点(三通道,包含C、M、Y三个值)各减去最小值

	vector<Mat> BGR;
	split(img, BGR);
	
	BGR[0] = 255 - BGR[0];
	BGR[1] = 255 - BGR[1];
	BGR[2] = 255 - BGR[2];

	Mat CMY(img.size(), CV_8UC3);
	merge(BGR, CMY);
	Mat minMat(img.size(), CV_8UC1);

	for (int i = 0; i < height; i++)
	{
		Vec3b *pImg = CMY.ptr<Vec3b>(i);
		uchar *pMin = minMat.ptr<uchar>(i);

		for (int j = 0; j < width; j++)
		{
			min = pImg[j][0];
			if (pImg[j][1] < min) min = pImg[j][1];
			if (pImg[j][2] < min) min = pImg[j][2];
			pMin[j] = min;
			for (int k = 0; k < 3; k++)
			{
				pImg[j][k] -= min;

			}
		}
	}

2.计算V的极大极小值。

void find_vhi_vlo(const Mat &img, double &vhi, double &vlo)
{
	int width = img.cols;
	int height = img.rows;

	uchar min;

	vector<Mat> BGR;
	split(img, BGR);
	//conver to CMY
	BGR[0] = 255 - BGR[0];
	BGR[1] = 255 - BGR[1];
	BGR[2] = 255 - BGR[2];

	Mat CMY(img.size(), CV_8UC3);
	merge(BGR, CMY);

	for (int i = 0; i < height; i++)
	{
		Vec3b *pImg = CMY.ptr<Vec3b>(i);
		for (int j = 0; j < width; j++)
		{
			min = pImg[j][0];
			if (pImg[j][1] < min) min = pImg[j][1];
			if (pImg[j][2] < min) min = pImg[j][2];
			for (int k = 0; k < 3; k++)
			{
				pImg[j][k] -= min;


			}
		}
	}
	Mat HSV = Mat(CMY.size(), CV_8UC3);
	cvtColor(CMY, HSV, COLOR_BGR2HSV);
	vector<Mat> vHSV;
	split(HSV, vHSV);

	////find Vmin and Vmax

	double vMin = 1.0;
	double vMax = .0;
	for (int i = 0; i < height; i++)
	{
		uchar *pImg = vHSV[2].ptr<uchar>(i);
		for (int j = 0; j < width; j++)
		{
			double v = (double)pImg[j] / 255.0;
			if (v > vMax)	vMax = v;
			if (v < vMin)	vMin = v;
		}
	}
	vhi = vMax;
	vlo = vMin;
}

3.重新量化V值:newPixel = oldPixel / 255- vMin) / (vMax - vMin)。

void quantizing_v(Mat &img, double vMax, double vMin)
{
	if (vMax == vMin)	return;
	if (img.channels() != 1)	return;

	int width = img.cols;
	int height = img.rows;

	
	for (int i = 0; i < height; i++)
	{
		uchar *pImg = img.ptr<uchar>(i);
		for (int j = 0; j < width; j++)
		{
			double newPixel = ((double)pImg[j] / vdelta - vMin) / (vMax - vMin);
			int tmp = int(newPixel * 255);
			if (tmp >255)
				pImg[j] = 255;
			else if (tmp < 0)
				pImg[j] = 0;
			else
				pImg[j] = (uchar)tmp;
		}
	}
}


4.按原步骤,将图像转换回去,得到颜色增强的图像。

	cvtColor(hsv, dst, COLOR_HSV2BGR);

	for (int i = 0; i < height; i++)
	{
		Vec3b *pDst = dst.ptr<Vec3b>(i);
		uchar *pMin = minMat.ptr<uchar>(i);

		for (int j = 0; j < width; j++)
		{
			for (int k = 0; k<3; k++)
			{
				int tmp = pDst[j][k] + pMin[j];
				if (tmp > 255)
					pDst[j][k] = 0;
				else
					pDst[j][k] = 255 - tmp;
			}

		}
	}

增强效果





四、不足

当然,这个算法比较简单,当图像亮度极大值比较小时,容易出现严重失真。并且,因为是全局处理的,当处理人像时,人的肤色部分容易出现过饱和现象。


附自己写的工程,结构比较乱,勉强能用。

测试工程

、改进

如果采用以上算法,对大像素图片的处理比较耗时消耗Cpu,幸好opencv提供了GPU的加速功能,利用OpenCV+Cuda,可以很好的实现加速功能,降低Cpu消耗。


自己写的供参考

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TalkU浩克

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值