【OpenCV】对比度增强之线性变换

原理讲解
输入的图像为I,宽为W,高为H,输出图像记为O,图像的线性变换可以利用以下公式定义:
在这里插入图片描述
当a=1,b=0时,O为I的一个副本;
如果a>1则输出图像O的对比度比I有所增大;
如果0 而b值的改变,影响的是输出的亮度,当b>0时,亮度增加;当b<0时,亮度减小。
举例:假设图像的灰度级范围是[50,100],通过a=2,b=0的线性变换,可以将输出图像的灰度级拉伸到[100,200],灰度级范围有所增加, 从而提高了对比度;而如果令a=0.5,b=0,则输出图像的灰度级会压缩到[25,50],灰度级范围有所减小,则降低了对比度。

实现方式
在OpenCV中实现一个常数与矩阵相乘有多种方式。
第一种方式:通过Mat的成员函数
Mat::convertTo(OutputArray m, int rtype,double alpha=1,double beta=0)
实现线性变换,该函数参数之间的关系如下:

m(x,y)=saturate_cast(alpha(*this)(x,y)+beta)

其中参数m代表输出矩阵,参数rtype是输出矩阵m的数据类型,参数alpha和beta分别可以理解为线性变换中的a和b.利用该函数实现线性变换的示例代码如下:

Mat I = (Mat_(2,2)<<0,200,23,4);
Mat O;
I.convertTo(0,CV_8UC1,2.0,0);

其中输入的I的数据类型为uchar,打印输出O的值,结果为:[[0,255],[46,8]] 也就是当输出矩阵的数据类型是CV_8U时,大于255的值会自动截断为255.

第二种方式:使用乘法运算符"*",仍然使用上述代码中的输入矩阵I,代码如下:

Mat O =3.5*I

输出矩阵O的值为[[0,255],[80,14]],使用乘法运算符”*“,无论常数是什么数据类型,输出矩阵的数据类型总是和输入矩阵的数据类型相同,当数据类型是CV_8U时,在返回值中将大于255的值自动截断为255.

第三种方式:利用OpenCV提供的函数
convertScaleAbs(InputArray src,OutputArray dst, double alpha=1,double beta=0)
其中参数的关系为dst=alpha*src+beta, dst的数据类型和输入矩阵src的数据类型是相同的。示例代码如下

Mat I=(Mat_(2,2)<<0,200,23,4);
Mat 0;
convertScaleAbs(I,O,2.0,0);

以上线性变换是对整个灰度级范围使用了相同的参数,有的时候也需要针对不用的灰度级范围进行不同的线性变换,这就是常用的分段线性变换,经常用于降低较亮或较暗区域的对比度来增强灰度级处于中间范围的对比度,或者压低中间灰度级处的对比度来增强较亮或较暗区域的对比度。
线性变换的参数需要根据不同的应用及图像自身的信息进行合理的选择,对于a和b的值需要进行多次的测试。

你可能感兴趣的:(Opencv)