基于OpenCV的灰度图像归一化到0~255(即对比度拉伸)的C++代码,并附原理介绍

灰度图像归一化到0~255(对比度拉伸)原理如下:

 g'  = g * Mult + Add

其中:

怎么理解这个原理?

 上面的原理把简单的事情搞复杂了,我们对上式进行化简,用Python-sympy进行化简,代码如下:

from sympy import *

g, Gmax, Gmin = symbols('g Gmax Gmin')
Mult = 255/(Gmax-Gmin)
Add = -Mult*Gmin
g_ = simplify(g*Mult+Add)
print(g_)

化简结果如下:

上面这个式子就很好理解了,上面的式子相当于把介于[Gmin,Gmax]区间的灰度值按比例拉伸到0~255的区间。 

原理就这么简单,接下来上代码,这个代码其实我之前就已经写过基于OpenCV1.x的版本了,详情可参见我写的另一篇博文,链接如下

https://blog.csdn.net/wenhao_ir/article/details/51142979

这篇博文提供的代码是基于OpenCV2.x的,并且没有使用OpenCV的函数cvMinMaxLoc()求阵列的最大值、最小值,有兴趣的同学可以参考我之前写过的代码,将下面代码中的求最大值、最小值的代码用OpenCV的cvMinMaxLoc()函数实现。

当然,以下代码最大的作用还是为大家学习图像处理基本原理之用。因为下面的代码完全可以被OpenCV的函数normalize()代替,即下面这条语句:

normalize(srcGray, resultImage, 0, 255, NORM_MINMAX);

我在之前的代码中也用到过这个归一化函数,比如下面这篇博文中的代码:

https://blog.csdn.net/wenhao_ir/article/details/51655055

关于OpenCV的函数normalize()的详细讲解,可参考博文https://blog.csdn.net/wenhao_ir/article/details/125619073

说回来,本文要提供给大家的源码如下:

源码中用到的图像的下载链接:

https://pan.baidu.com/s/1i4Dvm2h

//原文链接:https://blog.csdn.net/wenhao_ir/article/details/51658765

#include <opencv2/imgproc/imgproc.hpp>  
#include <opencv2/core/core.hpp>        
#include <opencv2/highgui/highgui.hpp> 
#include <iostream>  
cv::Mat contrastStretch(cv::Mat srcImage)
{
	cv::Mat resultImage = srcImage.clone();
	int nRows = resultImage.rows;
	int nCols = resultImage.cols;
	// 图像连续性判断
	if(resultImage.isContinuous())
	{
		nCols  = nCols  * nRows;
		nRows = 1;
	}
	// 图像指针操作
	uchar *pDataMat;
	int pixMax = 0, pixMin = 255;
	// 计算图像的最大最小值
	for(int j = 0; j <nRows; j ++)
	{
		pDataMat = resultImage.ptr<uchar>(j);
		for(int i = 0; i < nCols; i ++)
		{
			if(pDataMat[i] > pixMax)       
				pixMax = pDataMat[i];
			if(pDataMat[i] < pixMin)      
				pixMin = pDataMat[i];
		}
	}
    // 对比度拉伸映射
	for(int j = 0; j < nRows; j ++)
	{
		pDataMat = resultImage.ptr<uchar>(j);
		for(int i = 0; i < nCols; i ++)
		{
			pDataMat[i] = (pDataMat[i] - pixMin) * 
			    255 / (pixMax - pixMin);
		}
	}
	return resultImage;
}
int main()
{
	cv::Mat srcImage = cv::imread("lakeWater.jpg"); 
	if(!srcImage.data)
		return 0;	
	cv::Mat srcGray;
	cvtColor(srcImage, srcGray, CV_BGR2GRAY);	 
	imshow("srcGray", srcGray);
	cv::Mat resultImage = contrastStretch(srcGray);
	cv::imshow("resultImage", resultImage);	 
	cv::waitKey(0);	 
	return 0;
}

运行结果如下图所示:

这篇博文中我们是把对比度拉伸到了0~255的区间,也可以拉伸到自己指定的区间,详情见博文 https://blog.csdn.net/wenhao_ir/article/details/51604520

猜你喜欢

转载自blog.csdn.net/wenhao_ir/article/details/51658765