Opencv图像处理(图像的线性灰度变换)

图像增强简介
分段线性法变换原理
代码实现和效果预览
疫情期间,楼主作为大三学生每天除了要应付网课和作业之外还得抽出时间准备研究生考试。虽说少了很多时间学习自己喜欢的知识,但近期由于课程作业关系需要在matlab上实现简单的图像处理的操作,楼主自然的想到先前曾接触过的Opencv功能强大便考虑能否自己实现其中的一些函数,经过一下午的折腾也算简单的实现了一个简单的部分。
苦中作乐,特写下此篇博客记录一下。

一、图像增强简介

图像增强即增强图像中的有用信息,其目的是要改善图像的视觉效果。可以分为两大类:频率域和空间域。
频率域的图像增强方法有低通滤波、高通滤波等等,而在空间域常采用点运算和邻域运算(也成为空间域滤波)。本文主要介绍点运算中的灰度变换方法。
灰度变换方法又分为:
1.反转变换
2.线性变换
3.分段线性变换
4.对数变换
5.幂律变换(伽马变换)
其中为了突出感兴趣的目标或灰度区间,相对抑制那些不感兴趣的灰度区域,常采用分段线性法。

二、分段线性法变换原则

为突出感兴趣的目标或灰度区间,相对抑制不感兴趣的灰度区域,可采用分段线性变换。
一般我们采用的是***三段线性变换法***,其数学表达式为:
在这里插入图片描述
在这里插入图片描述

三、代码实现和效果预览

void test1() {
	/*获取RGB的像素值*/
	Mat dst;
	Mat src;
	src = imread("D:\\VS2017\\Project\\Based_opencv_DIP\\classic.jpg", 1);
	dst.create(src.size(), src.type());
	int height = dst.rows;
	int width = dst.cols;
	int cn = src.channels();//通道数
	int a = 256 * 0.3;
	int b = 256 * 0.6;
	int c = 256 * 0.1;
	int d = 256 * 0.9;
	int fa = (d - c) / (b - a);
	int fb = (255 - d) / (255 - b);
	for (int row = 0; row < height; row++)
	{
		for (int col = 0; col < width; col++)
		{
			if (cn == 1)
			{
				int gray = dst.at<uchar>(row, col);/*读取一个GRAY像素点的像素值(CV_8UC1)*/
				dst.at<uchar>(row, col) = fa * (gray - a) + c;;//对每一个像素线性变换

			}
			else if (cn == 3)//分段线性变换
			{
			//这里的判断语句可自行更改
				int blue = src.at<Vec3b>(row, col)[0];//第一个通道
				int green = src.at<Vec3b>(row, col)[1];//第二个通道
				int red = src.at<Vec3b>(row, col)[2];//第三个通道

				if (blue< a) {
					dst.at<Vec3b>(row, col)[0] = (c/a)*blue;
				}
				else if (blue > b) {
					dst.at<Vec3b>(row, col)[0] = fb *(blue - b)+d;
				}
				else
					dst.at<Vec3b>(row, col)[0] = fa * (blue - a) + c;

				if (green < a) {
					dst.at<Vec3b>(row, col)[1] = (c / a)*green;
				}
				else if (green > b) {
					dst.at<Vec3b>(row, col)[1] = fb * (green - b) + d;
				}
				else
					dst.at<Vec3b>(row, col)[1] = fa * (green - a) + c;

				if (red < a) {
					dst.at<Vec3b>(row, col)[2] = (c / a)*red;
				}
				else if (red > b) {
					dst.at<Vec3b>(row, col)[2] = fb * (red - b) + d;
				}
				else
					dst.at<Vec3b>(row, col)[2] = fa * (red - a) + c;
			}
		}
	}
	namedWindow("orignal image", WINDOW_AUTOSIZE);
	namedWindow("trans image", WINDOW_AUTOSIZE);
	imshow("orignal image", src);
	imshow("trans image", dst);
	imwrite("D:\\VS2017\\Project\\Based_opencv_DIP\\classic_trans.jpg", dst);
	waitKey(0);
}

在这里插入图片描述

		为了证实是否对图片进行了相对应的线性变换,进行一个小小的测试。将图片中的像素点读出写到txt文本中,对变换前后的图片像素进行比对来进行验证。其实现代码如下:
//将图片中的像素保存在txt当中
int main() {
	GdiplusStartupInput gdiplusstartupinput;
	ULONG_PTR gdiplustoken;
	GdiplusStartup(&gdiplustoken, &gdiplusstartupinput, NULL);

	wstring infilename(L"D:\\VS2017\\Project\\Based_opencv_DIP\\classic_trans.jpg");
	string outfilename("color3.txt");

	Bitmap* bmp = new Bitmap(infilename.c_str());
	UINT height = bmp->GetHeight();
	UINT width = bmp->GetWidth();
	cout << "width " << width << ", height " << height << endl;

	Color color;
	ofstream fout(outfilename.c_str());

	for (UINT y = 0; y < height; y++)
		for (UINT x = 0; x < width; x++) {
			bmp->GetPixel(x, y, &color);
			fout << x << "," << y << ";"
				<< (int)color.GetRed() << ","
				<< (int)color.GetGreen() << ","
				<< (int)color.GetBlue() << endl;
		}

	fout.close();

	delete bmp;
	GdiplusShutdown(gdiplustoken);
	system("pause");
	return 0;
}

通过对变换前后的两个图片的像素提取,对比两个txt文档我们即可验证所做变换的有效性。
color是变换前的

四、总结

千里之行,始于足下。许久没用过opencv的我重新使用起初确实还是有一些费力,加上一下午的测试让人的眼睛也很是疲劳。好在最后得到了应有的效果,非常感谢网上各种前辈留下的可供参考的代码,给了我很多代码上的提示,不懂的地方还有太多,但坚持下去总会有积少成多水滴石穿的一天。
希望大家能够一起学习进步。

参考

参考:将图像像素保存为txt文档

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值