前言:
😊😊😊欢迎来到本博客😊😊😊
🌟🌟🌟 本专栏主要结合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) << 0,180, 120, 35) ;
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) << 0,180, 120, 35) ;
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是学习图像处理理论知识比较好的一个途径,大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,有什么问题希望大家可以积极评论交流,我也会及时更新,来督促自己学习进度。希望大家觉得不错的可以点赞、关注、收藏。