美国物理学家埃德温∙兰德(Edwin Land) 在 1971 年提出一种被称为色彩的理论,并在颜色恒常性的基础上提出的一种图像增强方法。Retinex 理论认为物体的颜色是由物体对长波、中波和短波光线的反射能力决定的,而不是由反射光强度的绝对值决定的,即物体的色彩不受光照非均性的影响,具有一致性。
根据 Retinex 理论,它会将一幅给定的图像 S(x,y) 分解成两幅不同的图像:反射物体图像R(x,y)和入射光图像 L(x,y)。可以表示为:
其原理如下所示:
人眼得到的图像数据取决于入射光和物体表面对入射光的反射。Retinex理论就是通过图像S得到物体的反射性质R。所以实际上Retinex方法去除了入射光 L的性质最终得到了物体原本该有的样子。
SSR (Singal Scale Retinex),即单尺度视网膜算法是 Retinex 算法中最基础的一个算法。运用的就是上面的方法,具体步骤如下:
需要注意的是,最后一步量化的过程中,并不是将 Log[R(x,y)] 进行 Exp 化得到 R(x,y) 的结果,而是直接将 Log[R(x,y)] 的结果直接用如下公式进行量化:
该函数能改变图像的深度,而且可以实现原地改变。但是不能改变图像的通道数。
//函数原型
void convertTo(OutputArray dst, int rtype, double alpha, double beta, Stream& stream) const;
参数1:输出图像
参数2:需要的输出矩阵类型
参数3和参数4:缩放参数
缩放参数实际等价于公式:m(x,y) = saturate_cast(α(*this)(x,y)+β)
log()函数的功能是计算每个数组元素绝对值的自然对数
//函数原型
void log(InputArray src,OutputArray dst)
参数1:输入图像
参数2:输出图像(求对数以后的图像)
该函数归一化输入数组使它的范数或者数值范围在一定的范围内。
//函数原型
void normalize( InputArray src, InputOutputArray dst, double alpha = 1, double beta = 0,
int norm_type = NORM_L2, int dtype = -1, InputArray mask = noArray());
参数1:输入图像
参数2:输出图像
参数3:范围下限
参数4:范围上限
参数5:选择归一化的方式
参数6: 当为负,输出在大小深度通道数都等于输入,当为正,输出只在深度与输如不同。
一般的图像文件格式使用的是 Unsigned 8bits吧,CvMat矩阵对应的参数类型就是CV_8UC1,CV_8UC2,CV_8UC3。 其中U代表 Unsigned 无符号、C代表CvMat 后面的数字代表通道数(最后的1、2、3表示通道数,譬如RGB3通道就用CV_8UC3)
float 是32位的,对应CvMat数据结构参数就是:CV_32FC1,CV_32FC2,CV_32FC3...
double是64bits,对应CvMat数据结构参数:CV_64FC1,CV_64FC2,CV_64FC3。
Vec2b—表示每个Vec2b对象中,可以存储2个char(字符型)数据
Vec3b—表示每一个Vec3b对象中,可以存储3个char(字符型)数据,比如可以用这样的对象,去存储RGB图像中的
Vec4b—表示每一个Vec4b对象中,可以存储4个字符型数据,可以用这样的类对象去存储—4通道RGB+Alpha的图
void SingleScaleRetinex(const Mat& src, Mat& dst, int sigma)
{
Mat doubleImage, gaussianImage, logIImage, logGImage, logRImage;
//转换范围,所有图像元素增加1.0保证log操作正常,防止溢出
src.convertTo(doubleImage, CV_64FC3, 1.0, 1.0);
//高斯模糊,当size为零时将通过sigma自动进行计算
GaussianBlur(doubleImage, gaussianImage, Size(0, 0), sigma);
//OpenCV的log函数可以计算出对数值。logIImage和logGImage就是对数计算的结果。
log(doubleImage, logIImage);
log(gaussianImage, logGImage);
//Retinex公式,Log(R(x,y))=Log(I(x,y))-Log(G(x,y)))
logRImage = logIImage - logGImage;
//将结果量化到[0,255]范围内,NORM_MINMAX表示线性量化,CV_8UC3表示将图像转回
normalize(logRImage, dst, 0, 255, NORM_MINMAX, CV_8UC3);
}
图像增加结果