Opencv图像增强算法(对比度增强)-opencv

由于项目需要,这几天找了网上一个基于opencv的图像对比度增强算法的博客。但算法发布的日期太过久远了,2012年的代码放到现在很多类和类方法已经不再适用于新版本的opencv库了。所以我花了点时间重写了一下,并加入一些个人对于算法的理解与优化。


目标原代码:

《Opencv 图像增强算法 图像检测结果》
https://blog.csdn.net/abcjennifer/article/details/7401921
《opencv 彩色图像对比度增强》
https://blog.csdn.net/abcjennifer/article/details/7428737


对等重写:

对等重写就是原博客怎么写,我就怎么写,只是把一些已经弃用的类、方法、宏给替换掉而已。相当于就是翻新,然后加入一些个人理解的注释。

增强函数

/***********************************************************
增强算法的原理在于先统计每个灰度值在整个图像中所占的比例
然后以小于当前灰度值的所有灰度值在总像素中所占的比例,作为增益系数
对每一个像素点进行调整。由于每一个值的增益系数都是小于它的所有值所占
的比例和。所以就使得经过增强之后的图像亮的更亮,暗的更暗。
************************************************************/
void ImageStretchByHistogram(const Mat & src, Mat & dst)
{
	//判断传入参数是否正常
	if (!(src.size().width == dst.size().width))
	{
		cout << "error" << endl;
		return;
	}
	double p[256], p1[256], num[256];

	memset(p, 0, sizeof(p));
	memset(p1, 0, sizeof(p1));
	memset(num, 0, sizeof(num));
	int height = src.size().height;
	int width = src.size().width;
	long wMulh = height * width;

	//统计每一个灰度值在整个图像中所占个数
	for (int x = 0; x < width; x++)
	{
		for (int y = 0; y < height; y++)
		{
			uchar v = src.at<uchar>(y, x);
			num[v]++;
		}
	}

	//使用上一步的统计结果计算每一个灰度值所占总像素的比例
	for (int i = 0; i < 256; i++)
	{
		p[i] = num[i] / wMulh;
	}

	//计算每一个灰度值,小于当前灰度值的所有灰度值在总像素中所占的比例
	//p1[i]=sum(p[j]);	j<=i;
	for (int i = 0; i < 256; i++)
	{
		for (int k = 0; k <= i; k++)
			p1[i] += p[k];
	}

	//以小于当前灰度值的所有灰度值在总像素中所占的比例,作为增益系数对每一个像素点进行调整。
	for (int y = 0; y < height; y++)
	{
		for (int x = 0; x < width; x++) {
			uchar v = src.at<uchar>(y, x);
			dst.at<uchar>(y, x) = p1[v] * 255 + 0.5;
		}
	}
	return;
}

单通道灰度图增强函数

//调整图像对比度
Mat AdjustContrastY(const Mat & img)
{
	Mat out = Mat::zeros(img.size(), CV_8UC1);
	Mat workImg = img.clone();

	//对图像进行对比度增强
	ImageStretchByHistogram(workImg, out);

	return Mat(out);
}

三通道彩图增强函数

//调整图像对比度
Mat AdjustContrast(const Mat & img)
{
	Mat out;

	Mat Y = Mat::zeros(img.size(), CV_8UC1);
	Mat Cb = Mat::zeros(img.size(), CV_8UC1);
	Mat Cr = Mat::zeros(img.size(), CV_8UC1);
	Mat Compile_YCbCr = Mat::zeros(img.size(), CV_8UC3);
	Mat dst = Mat::zeros(img.size(), CV_8UC1);

	int i;
	/*******************************************
	对比度增强算法本质上就是对图像Y分量进行调整。
	所以需要先把图像数据从BGR转换为YUV,YCrCb就是YUV
	然后再对YUV数据进行拆分,最后单独对Y分量进行调整。
	********************************************/
	cvtColor(img, Compile_YCbCr, cv::COLOR_BGR2YCrCb);
	//定义一个Mat向量容器保存拆分后的数据
	vector<Mat> channels;
	//进行图像通道拆分
	split(Compile_YCbCr, channels);
	channels.at(0).copyTo(Y);
	channels.at(1).copyTo(Cb);
	channels.at(2).copyTo(Cr);
	
	//单独对Y分量进行调整
	ImageStretchByHistogram(Y, dst);

	//把对比度增强后的Y分量与原来的U、V分量重组为新的图像
	for (int y = 0; y < img.size().height; y++)
	{
		for (int x = 0; x < img.size().width; x++)
		{
			//拼接一个像素的三通道
			Mat cur = Mat::zeros(3, 1, CV_32FC1);
			cur.at<float>(0, 0) = dst.at<uchar>(y, x);
			cur.at<float>(1, 0) = Cb.at<uchar>(y, x);
			cur.at<float>(2, 0) = Cr.at<uchar>(y, x);

			//三通道顺序写入
			for (i = 0; i < 3; i++)
			{
				double xx = cur.at<float>(i, 0);
				(Compile_YCbCr).at<Vec3b>(y, x)[i] = xx;
			}
		}
	}
	//把重组之后的图像转换回BGR数据进行返回
	cvtColor(Compile_YCbCr, out, COLOR_YCrCb2BGR);

	return Mat(out);
}

优化重写

优化重写注意是针对三通道彩图增强函数“AdjustContrast()”这个函数的,这主要是由于原算法本身就存在一定的问题和在当前的opencv版本下存在一定的改进空间。就像原博客中的dst1定义的是3通道,但增强函数“ImageStretchByHistogram()”内部处理的时候只是使用了当通道进行赋值,虽然可以正常运行,但却容易让阅读代码的人产生误解(例如我),而且在新版本opencv的语法环境下会存在问题(原博客评论区就有人遇到了这个语法问题,我上面的代码中通过修改部分代码逻辑解决了这个问题)。且在测试中发现,三通道彩图的增强函数运行速度过慢。
所以我针对三通道彩图增强函数“AdjustContrast()”这个函数进行了重写。

//三通道彩图增强函数
Mat AdjustContrast(const Mat & img)
{
	Mat out = Mat::zeros(img.size(), CV_8UC3);
	Mat Compile_YCbCr = Mat::zeros(img.size(), CV_8UC3);
	Mat dst = Mat::zeros(img.size(), CV_8UC1);

	//进行BGR转YUV
	cvtColor(img, Compile_YCbCr, cv::COLOR_BGR2YCrCb);

	//定义一个Mat向量容器保存拆分后的数据
	vector<Mat> channels;
	//进行图像通道拆分
	split(Compile_YCbCr, channels);
	//单独对Y分量进行调整
	ImageStretchByHistogram(channels.at(0), dst);
	//把调整后的Y分量替换原来的Y分量
	dst.copyTo(channels.at(0));
	//进行通道的合并
	merge(channels, Compile_YCbCr);

	//把重组之后的图像转换回BGR数据进行返回
	cvtColor(Compile_YCbCr, out, COLOR_YCrCb2BGR);
	return Mat(out);
}

灰度效果:

增强前
在这里插入图片描述
增强后
在这里插入图片描述


彩图效果:

增强前
在这里插入图片描述
增强后
在这里插入图片描述


相关参考:

《CvMat用法详解》
https://blog.csdn.net/zx3517288/article/details/51760541
《OpenCV类型CV_32F和CV_32FC1之间的差异(OpenCV类型CV_32F和CV_32FC1之间的差异)》
https://www.it1352.com/541681.html
《opencv Mat 多通道 数据读取或赋值》
https://blog.csdn.net/xuexiaokkk/article/details/50251511
《openCv:IplImage的变量imageData解释》
https://blog.csdn.net/aic1999/article/details/83040442
《opencv split和merge操作》
https://blog.csdn.net/omuyejingfeng1/article/details/25685141
《opencv中cvSplit函数讲解》
https://blog.csdn.net/yankai0219/article/details/6630911
《opencv笔记——cvCreateImage函数说明》
https://blog.csdn.net/breeze5428/article/details/30050327
《IplImage结构体 nChannels depth含义》
https://blog.csdn.net/qq_41972382/article/details/89225522


零BUG是原则性问题。

  • 8
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
引用:在OpenCV中,可以通过调整图像对比度增强彩色图像。通过使用直方图均衡化方法,可以增加图像的动态范围,使得图像中的细节更加清晰可见。直方图均衡化是一种将图像的灰度级分布均匀映射到整个灰度级范围的方法,从而增强图像对比度。可以使用cv::equalizeHist函数来实现彩色图像的直方图均衡化。首先,将彩色图像转换成YCrCb颜色空间,然后对亮度分量(Y通道)进行直方图均衡化,最后将图像转换回BGR颜色空间。 引用:为了优化彩色图像增强对比度的函数,可以进行重写。可以使用cv::cvtColor函数将彩色图像转换为YCrCb颜色空间,然后对亮度分量进行直方图均衡化。接下来,将调整后的亮度分量替换原来的亮度分量,并将图像转换回BGR颜色空间以得到增强对比度的彩色图像。这样的重写可以提高函数的运行速度并解决一些语法问题。 因此,对于彩色图像增强对比度,可以使用OpenCV中的直方图均衡化方法,或通过重写函数来实现。通过将彩色图像转换为<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Opencv图像增强算法对比度增强)-opencv](https://blog.csdn.net/L_0x0b/article/details/111314937)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值