zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【图像处理OpenCV(C++版)】——4.4 对比度增强之伽马变换

OpencvC++图像处理 增强 变换 4.4 对比度
2023-09-14 09:15:09 时间

前言

😊😊😊欢迎来到本博客😊😊😊

🌟🌟🌟 本专栏主要结合OpenCV和C++来实现一些基本的图像处理算法并详细解释各参数含义,适用于平时学习、工作快速查询等,随时更新。

😊😊😊 具体食用方式:可以点击本专栏【OpenCV快速查找(更新中)】–>搜索你要查询的算子名称或相关知识点,或者通过这篇博客👉通俗易懂OpenCV(C++版)详细教程——OpenCV函数快速查找(不断更新中)]查阅你想知道的知识,即可食用。

🎁🎁🎁支持:如果觉得博主的文章还不错或者您用得到的话,可以悄悄关注一下博主哈,如果三连收藏支持就更好啦!这就是给予我最大的支持!😙😙😙


学习目标

  • 熟悉伽马变换概念及原理
  • C++实现伽马变换案例

一、概念及原理

  假设输入图像为I,高为H、宽为W伽马变换需要对输入图像进行归一化处理(对于8位图而言,除以255即可)I(r,c) 代表归一化后第r行第c列的灰度值,输出图像记作O(r,c)。伽马变换原理如下:

  r为灰度图像的归一化后输入值,取值范围为[0,1]。s为经过伽马变换后的灰度输出值。c为灰度缩放系数,通常取1。γ为伽马因子大小。控制了整个变换的缩放程度。如下图所示:

  当γ=1时,图像不变。如果图像整体或者感兴趣区域较暗则令0<γ<1可以增加图像对比度;相反,如果图像整体或者感兴趣区域较亮则令γ<1可以降低图像对比度


二、代码实现

  OpenCV提供了函数,对每个值进行幂运算:

void pow(InputArray src,double power,OutputArray dst)
src:输入
power:指数值,即γ值
dst:输出,类型与输入一致

  我们来看一个简单案例:


#include <iostream>
#include <opencv2/opencv.hpp> 
# include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace CV ;
int main() {
	Mat I = (Mat_ <float>(2, 2) << 018012035) ;
	Mat 0;
	pow(I,2, 0) ;
	cout<< "0:" << 0 << endl;
return 0;

  因为I的数据类型是CV_32F,所以O的数据类型也是CV_32F计算出来的值会超过255

  如果将I的数据类型换成CV_8U,代码如下:


#include <iostream>
#include <opencv2/opencv.hpp> 
# include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace CV ;
int main() {
	Mat I = (Mat_ <uchar>(2, 2) << 018012035) ;
	Mat 0;
	pow(I,2, 0) ;
	cout<< "0:" << 0 << endl;
return 0;

  如果原矩阵是CV_8U类型的,那么在进行幂运算时,大于255的值会自动截断为255

  如果想对图像进行伽马变换时,先将图像的灰度值归一化[0,1]范围,然后再进行幂运算。代码如下:


#include <iostream>
#include <opencv2/opencv.hpp> 
# include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace CV ;
int main() {
	Mat I = imread("D:/VSCodeFile/OpenCV_CSDN/image/logo.jpeg",IMREAD_COLOR);
	
	//归一化
	Mat FI;
	I.convertTo(FI,CV_64F,1.0/255,0)
	
	//伽马变换
	double gamma = 0.1;
	Mat Out;
	pow(FI,gamma,Out);//Out与FI有相同数据类型

	//效果图展示
	imshow("原图", I);
	imshow("After Gamma",Out);
	
	waitKey(0);
	return 0;
}

  如果想本地保存O,则还需要将灰度值变为在[0,255]之间且转换为CV_8U类型。如果没有数据类型转换,则直接保存浮点型的O,这样虽然不会报错,但是保存后图像呈现黑色,看不到任何信息。代码如下:


#include <iostream>
#include <opencv2/opencv.hpp> 
# include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace CV ;
int main() {
	Mat I = imread("D:/VSCodeFile/OpenCV_CSDN/image/logo.jpeg",IMREAD_COLOR);
	
	//归一化
	Mat FI;
	I.convertTo(FI,CV_64F,1.0/255,0)
	
	//伽马变换
	double gamma = 0.1;
	Mat Out;
	pow(FI,gamma,Out);//Out与FI有相同数据类型

	//效果图展示
	imshow("原图", I);
	imshow("After Gamma",Out);
	
	//===================
	imwrite("D:/VSCodeFile/OpenCV__CSDN/image/BeforeConvert_logo.jpeg", Out);
	Out.convertTo(Out,CV_8U,255,0)
	imwrite("D:/VSCodeFile/OpenCV__CSDN/image/after_Gamma_logo.jpeg", Out);
	//===================
	
	waitKey(0);
	return 0;
}

  函数介绍:

convertTo(dst, type, scale, shift)
作用:把一个矩阵从一种数据类型转换到另-种数据类型,同时可以带上缩放因子和增量

dst:目的矩阵,如果dst在运算前没有合适的尺寸或类型,将被重新分配。
type:需要的输出矩阵类型,或者更明确的,是输出矩阵的深度,如果是负值(常用-1)则输出矩阵和输入矩阵类型相同
scale:尺度变换因子(可选)。默认值是1。即把原矩阵中的每一个元素都乘以scale。
shift:附加到尺度变换后的值上的偏移量(可选) 。默认值是0。即把原矩阵中的每一个元素都乘以scale,再加上shift。

计算方式:dst=src*scale+shift

示例:Input.convertTo(tmp,CV_8U,255,255);
注释:将矩阵Input转换为CV_8U类型的矩阵tmp: tmp(x,y)= Input(x,y)*255+255.这样,将图像做线性变换。
使值为-1的像素变为0 (-1*255+255=0)。值大于255的像素将赋值为255,这是因为CV32S转换为无符号CV_8U时,应用了饱和度运算。

  伽马变换在提升对比度上有比较好的效果,但是需要手动调节γ值。下一节将会介绍更为方便的方法自动调节图像对比度。


五、 总结

  最后,长话短说,大家看完就好好动手实践一下,切记不能三分钟热度、三天打鱼,两天晒网。OpenCV是学习图像处理理论知识比较好的一个途径,大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,有什么问题希望大家可以积极评论交流,我也会及时更新,来督促自己学习进度。希望大家觉得不错的可以点赞、关注、收藏。


🚶🚶🚶 今天的文章就到这里啦~
喜欢的话,点赞👍、收藏⭐️、关注💟哦 ~