《数字图像处理》灰度的分段线性变换之对比度拉伸-C++源码

原理见《数字图像处理》第三版3.2.4

输出灰度和输入灰度的关系如下图

《数字图像处理》灰度的分段线性变换之对比度拉伸-C++源码_第1张图片

现在令(r1,s1)=(rmin,0);(r2,s2)=(rmax,L-1)和(r1,s1)=(m,0);(r2,s2)=(m,L-1),m为灰度均值

代码如下(VS2013+OpenCV3.0)

/*
//***************************************************************************************
//-----------------------------------------------作者:我三食堂不服-----------------------
//***************************************************************************************
*/


#include   
#include 

using namespace std;
using namespace cv;

/*
//图像对比度拉伸。
//(r1,s1)灰度平面上的第一个点
//(r2,s2)灰度平面上的第二个点
*/
Mat Stretch(Mat input, int r1, int s1, int r2, int s2);

//获取图片灰度值最大值与最小值
int RmimRmax(Mat input, int &rmin, int& rmax);

//获取图像平均灰度值
int Average(Mat input);



int main(int argc, char** argv)
{
	Mat im_source;			        	//原图
	Mat im_pro;					//处理后的图片
	Mat im_pro2;					//处理后的图片

	//载入原图(灰度图方式)
	im_source = imread("3-10_b.tif", IMREAD_GRAYSCALE);

	//图片处理
	int rmin{ 255 };
	int rmax{ 0 };
	RmimRmax(im_source, rmin, rmax);
	im_pro = Stretch(im_source, rmin, 0, rmax, 255);
	int m = Average(im_source);
	im_pro2 = Stretch(im_source, m, 0, m, 255);

	//创建窗口
	namedWindow("【原图】");
	namedWindow("【处理后】");
	namedWindow("【处理后2】");

	//显示图片
	imshow("【原图】", im_source);
	imshow("【处理后】", im_pro);
	imshow("【处理后2】", im_pro2);

	//保存图片
	imwrite("3-10_c.tif", im_pro);
	imwrite("3-10_d.tif", im_pro2);

	//等待键盘操作
	cvWaitKey(0);

	return 0;
}



/*
//图像对比度拉伸。
//(r1,s1)灰度平面上的第一个点
//(r2,s2)灰度平面上的第二个点
*/
Mat Stretch(Mat input, int r1, int s1, int r2, int s2)
{
	int h{ input.rows };				// 图片高
	int w{ input.cols };				// 图片宽
	Mat out{ h, w, CV_8UC1 };			// 输出图片
	uchar* data_in{ input.data };		// 原图图片像素数据
	uchar* data_out{ out.data };		// 输出图片像素数据
	double data;						// 临时灰度值

	double a, a1, a2, a3, b, b1, b2, b3;		// 直线斜率与截距
	a1 = (double)s1 / (double)r1;
	b1 = 0;
	a2 = (double)(s2 - s1) / (double)(r2 - r1);
	b2 = s1 - a2*r1;
	a3 = (255.0 - s2) / (255.0 - r2);
	b3 = s2 - a3*r2;


	for (int y = 0; y < h; y++)
	for (int x = 0; x < w; x++)
	{
		data = data_in[y*w + x];
		if (data <= r1)
		{
			a = a1;
			b = b1;
		}
		else if (data >= r2)
		{
			a = a3;
			b = b3;
		}
		else
		{
			a = a2;
			b = b2;
		}
		data = a*data + b;

		data_out[y*w + x] = (uchar)(data);
	}

	return out;
}


//获取图片灰度值最大值与最小值
int RmimRmax(Mat input, int &rmin, int& rmax)
{
	int h{ input.rows };				// 图片高
	int w{ input.cols };				// 图片宽
	uchar* data_in{ input.data };		// 原图图片像素数据

	for (int y = 0; y < h; y++)
	for (int x = 0; x < w; x++)
	{
		if (rmin>data_in[y*w + x])
			rmin = data_in[y*w + x];

		if (rmax < data_in[y*w + x])
			rmax = data_in[y*w + x];
		
	}

	return 0;
}

//获取图像平均灰度值
int Average(Mat input)
{
	long long re{ 0 };
	int h{ input.rows };				// 图片高
	int w{ input.cols };				// 图片宽
	uchar* data_in{ input.data };		// 原图图片像素数据

	for (int y = 0; y < h; y++)
	for (int x = 0; x < w; x++)
	{
		re += data_in[y*w + x];
	}
	re /= (h*w);

	return (int)re;
}

效果如下:

《数字图像处理》灰度的分段线性变换之对比度拉伸-C++源码_第2张图片 原图
《数字图像处理》灰度的分段线性变换之对比度拉伸-C++源码_第3张图片 处理后
《数字图像处理》灰度的分段线性变换之对比度拉伸-C++源码_第4张图片 处理后

 

你可能感兴趣的:(数字图像处理,OpenCV,对比度拉伸,灰度变换)